ATLAS Offline Software
ArenaHeapSTLAllocator.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3 */
4 /**
5  * @file AthAllocators/ArenaHeapSTLAllocator.icc
6  * @author scott snyder
7  * @date Nov 2011
8  * @brief STL-style allocator wrapper for @c ArenaHeapAllocator.
9  */
10 
11 
12 #include <cassert>
13 
14 
15 namespace SG {
16 
17 
18 
19 //****************************************************************************
20 // Generic specialization
21 //
22 
23 
24 /**
25  * @brief Constructor.
26  * @param nblock Value to set in the parameters structure for the
27  * number of elements to allocate per block.
28  * @param name Value to set in the parameters structure for the
29  * allocator name.
30  */
31 template <class T>
32 ArenaHeapSTLAllocator_initParams<T>::ArenaHeapSTLAllocator_initParams
33  (size_t nblock /*= 1000*/, const std::string& name /*= ""*/)
34  : Base (nblock, name)
35 {
36 }
37 
38 
39 /**
40  * @brief Return an initialized parameters structure.
41  */
42 template <class T>
43 ArenaAllocatorBase::Params ArenaHeapSTLAllocator_initParams<T>::params() const
44 {
45  // Do the base class stuff.
46  ArenaAllocatorBase::Params p =
47  Base::operator ArenaAllocatorBase::Params();
48 
49  // Disable ctor/dtor.
50  p.constructor = 0;
51  p.destructor = 0;
52 
53  // Overlap link over free struct.
54  p.eltSize = std::max (sizeof(T), p.minSize);
55  p.linkOffset = 0;
56 
57  return p;
58 }
59 
60 
61 /**
62  * @brief Default constructor.
63  * @param nblock Value to set in the parameters structure for the
64  * number of elements to allocate per block.
65  * @param name Value to set in the parameters structure for the
66  * allocator name.
67  */
68 template <class T, class VETO>
69 // cppcheck-suppress uninitMemberVar ; false positive
70 ArenaHeapSTLAllocator<T, VETO>::ArenaHeapSTLAllocator
71  (size_t nblock /*= 1000*/, const std::string& name /*= ""*/)
72  : m_pool (ArenaHeapSTLAllocator_initParams<T> (nblock, name))
73 {
74 }
75 
76 
77 /**
78  * @brief Copy constructor.
79  *
80  * The @c name and @c nblock parameters are copied, but the data are not.
81  */
82 template <class T, class VETO>
83 // cppcheck-suppress uninitMemberVar ; false positive
84 ArenaHeapSTLAllocator<T, VETO>::ArenaHeapSTLAllocator
85  (const ArenaHeapSTLAllocator& a)
86  : m_pool (ArenaHeapSTLAllocator_initParams<T> (a.nblock(), a.name()))
87 {
88 }
89 
90 
91 /**
92  * @brief Constructor from another @c ArenaHeapSTLAllocator.
93  *
94  * The @c name and @c nblock parameters are copied, but the data are not.
95  */
96 template <class T, class VETO>
97 template <class U, class V>
98 // cppcheck-suppress uninitMemberVar ; false positive
99 ArenaHeapSTLAllocator<T, VETO>::ArenaHeapSTLAllocator
100  (const ArenaHeapSTLAllocator<U, V>& a)
101  : m_pool (ArenaHeapSTLAllocator_initParams<T> (a.nblock(), a.name()))
102 {
103 }
104 
105 
106 /**
107  * @brief Move constructor.
108  *
109  * Move the data.
110  */
111 template <class T, class VETO>
112 ArenaHeapSTLAllocator<T, VETO>::ArenaHeapSTLAllocator
113  (ArenaHeapSTLAllocator&& a)
114  : m_pool (std::move (a.m_pool))
115 {
116 }
117 
118 
119 /**
120  * @brief Move constructor.
121  *
122  * Move the data.
123  */
124 template <class T, class VETO>
125 ArenaHeapSTLAllocator<T, VETO>&
126 ArenaHeapSTLAllocator<T, VETO>::operator= (ArenaHeapSTLAllocator&& a)
127 {
128  if (this != &a) {
129  m_pool = std::move (a.m_pool);
130  }
131  return *this;
132 }
133 
134 
135 /**
136  * @brief Swap.
137  */
138 template <class T, class VETO>
139 void ArenaHeapSTLAllocator<T, VETO>::swap (ArenaHeapSTLAllocator& a)
140 {
141  m_pool.swap (a.m_pool);
142 }
143 
144 
145 /**
146  * @brief Equality test.
147  *
148  * Two allocators should compare equal if objects allocated by one
149  * can be deallocated by the other. We should just check if they
150  * are the same object.
151  */
152 template <class T, class VETO>
153 inline
154 bool ArenaHeapSTLAllocator<T, VETO>::operator==
155  (const ArenaHeapSTLAllocator& other) const
156 {
157  return this == &other;
158 }
159 
160 
161 /**
162  * @brief Inequality test.
163  *
164  * Two allocators should compare equal if objects allocated by one
165  * can be deallocated by the other. We should just check if they
166  * are the same object.
167  */
168 template <class T, class VETO>
169 inline
170 bool ArenaHeapSTLAllocator<T, VETO>::operator!=
171  (const ArenaHeapSTLAllocator& other) const
172 {
173  return this != &other;
174 }
175 
176 
177 /**
178  * @brief Return allocator to use for a copy-constructed container.
179  *
180  * When we copy-construct a container, we want the new allocator
181  * to copy parameters from the old one, but not the data.
182  */
183 template <class T, class VETO>
184 inline
185 ArenaHeapSTLAllocator<T, VETO>
186 ArenaHeapSTLAllocator<T, VETO>::select_on_container_copy_construction() const
187 {
188  return ArenaHeapSTLAllocator (nblock(), name());
189 }
190 
191 
192 /**
193  * @brief Convert a reference to an address.
194  */
195 template <class T, class VETO>
196 inline
197 typename ArenaHeapSTLAllocator<T, VETO>::pointer
198 ArenaHeapSTLAllocator<T, VETO>::address (reference x) const
199 {
200  return &x;
201 }
202 
203 
204 /**
205  * @brief Allocate new objects.
206  * @param n Number of objects to allocate. Must be 1.
207  * @param hint Allocation hint. Not used.
208  */
209 template <class T, class VETO>
210 inline
211 typename ArenaHeapSTLAllocator<T, VETO>::pointer
212 ArenaHeapSTLAllocator<T, VETO>::allocate (size_type
213 #ifndef NDEBUG
214  n
215 #endif
216  , const void* /*hint = 0*/)
217 {
218  assert (n == 1);
219  return reinterpret_cast<pointer> (m_pool.allocate());
220 }
221 
222 
223 /**
224  * @brief Deallocate objects.
225  * @param n Number of objects to deallocate. Must be 1.
226  *
227  * This implementation doesn't do anything.
228  */
229 template <class T, class VETO>
230 inline
231 void ArenaHeapSTLAllocator<T, VETO>::deallocate (pointer p, size_type
232 #ifndef NDEBUG
233  n
234 #endif
235  )
236 {
237  assert (n == 1);
238  using pointer_nc = std::remove_const_t<T>*;
239  pointer_nc pp ATLAS_THREAD_SAFE = const_cast<pointer_nc>(p);
240  m_pool.free (reinterpret_cast<ArenaHeapAllocator::pointer> (pp));
241 }
242 
243 
244 /**
245  * @brief Return the maximum number of objects we can allocate at once.
246  *
247  * This always returns 1.
248  */
249 template <class T, class VETO>
250 inline
251 typename ArenaHeapSTLAllocator<T, VETO>::size_type
252 ArenaHeapSTLAllocator<T, VETO>::max_size() const throw()
253 {
254  return 1;
255 }
256 
257 
258 /**
259  * @brief Call the @c T constructor.
260  * @param p Location of the memory.
261  * @param args Arguments to pass to the constructor.
262  */
263 template <class T, class VETO>
264 template <class... Args>
265 inline
266 void ArenaHeapSTLAllocator<T, VETO>::construct (pointer p, Args&&... args)
267 {
268  new (p) T(std::forward<Args>(args)...);
269 }
270 
271 
272 /**
273  * @brief Call the @c T destructor.
274  * @param p Location of the memory.
275  */
276 template <class T, class VETO>
277 inline
278 void ArenaHeapSTLAllocator<T, VETO>::destroy (pointer p)
279 {
280  p->~T();
281 }
282 
283 
284 /**
285  * @brief Return the hinted number of objects allocated per block.
286  */
287 template <class T, class VETO>
288 inline
289 size_t ArenaHeapSTLAllocator<T, VETO>::nblock() const
290 {
291  return m_pool.params().nblock;
292 }
293 
294 
295 /**
296  * @brief Return the name of this allocator.
297  */
298 template <class T, class VETO>
299 inline
300 const std::string& ArenaHeapSTLAllocator<T, VETO>::name() const
301 {
302  return m_pool.name();
303 }
304 
305 
306 /**
307  * @brief Free all allocated elements.
308  *
309  * All elements allocated are returned to the free state.
310  * @c clear should be called on them if it was provided.
311  * The elements may continue to be cached internally, without
312  * returning to the system.
313  */
314 template <class T, class VETO>
315 void ArenaHeapSTLAllocator<T, VETO>::reset()
316 {
317  m_pool.reset();
318 }
319 
320 
321 /**
322  * @brief Free all allocated elements and release memory back to the system.
323  *
324  * All elements allocated are freed, and all allocated blocks of memory
325  * are released back to the system.
326  * @c destructor should be called on them if it was provided
327  * (preceded by @c clear if provided and @c mustClear was set).
328  */
329 template <class T, class VETO>
330 void ArenaHeapSTLAllocator<T, VETO>::erase()
331 {
332  m_pool.erase();
333 }
334 
335 
336 /**
337  * @brief Set the total number of elements cached by the allocator.
338  * @param size The desired pool size.
339  *
340  * This allows changing the number of elements that are currently free
341  * but cached. Any allocated elements are not affected by this call.
342  *
343  * If @c size is greater than the total number of elements currently
344  * cached, then more will be allocated. This will preferably done
345  * with a single block, but that is not guaranteed; in addition, the
346  * allocator may allocate more elements than is requested.
347  *
348  * If @c size is smaller than the total number of elements currently
349  * cached, as many blocks as possible will be released back to the system.
350  * It may not be possible to release the number of elements requested;
351  * this should be implemented on a best-effort basis.
352  */
353 template <class T, class VETO>
354 void ArenaHeapSTLAllocator<T, VETO>::reserve (size_t size)
355 {
356  m_pool.reserve (size);
357 }
358 
359 
360 /**
361  * @brief Return the statistics block for this allocator.
362  */
363 template <class T, class VETO>
364 ArenaAllocatorBase::Stats ArenaHeapSTLAllocator<T, VETO>::stats() const
365 {
366  return m_pool.stats();
367 }
368 
369 
370 /**
371  * @brief Return a pointer to the underlying allocator (may be 0).
372  */
373 template <class T, class VETO>
374 const ArenaBlockAllocatorBase* ArenaHeapSTLAllocator<T, VETO>::poolptr() const
375 {
376  return &m_pool;
377 }
378 
379 
380 /**
381  * @brief Write-protect the memory managed by this allocator.
382  *
383  * Adjust protection on the memory managed by this allocator
384  * to disallow writes.
385  */
386 template <class T, class VETO>
387 inline
388 void ArenaHeapSTLAllocator<T, VETO>::protect()
389 {
390  m_pool.protect();
391 }
392 
393 
394 /**
395  * @brief Write-enable the memory managed by this allocator.
396  *
397  * Adjust protection on the memory managed by this allocator
398  * to allow writes.
399  */
400 template <class T, class VETO>
401 inline
402 void ArenaHeapSTLAllocator<T, VETO>::unprotect()
403 {
404  m_pool.unprotect();
405 }
406 
407 
408 //****************************************************************************
409 // Vetoed specialization.
410 //
411 
412 
413 /**
414  * @brief Default constructor.
415  * @param nblock Value to set in the parameters structure for the
416  * number of elements to allocate per block.
417  * @param name Value to set in the parameters structure for the
418  * allocator name.
419  */
420 template <class T>
421 // cppcheck-suppress uninitMemberVar ; false positive
422 ArenaHeapSTLAllocator<T, T>::ArenaHeapSTLAllocator
423  (size_t nblock /*= 1000*/, const std::string& name /*= ""*/)
424  : m_nblock (nblock),
425  m_name (name),
426  m_poolptr (0)
427 {
428 }
429 
430 
431 /**
432  * @brief Constructor from another @c ArenaHeapSTLAllocator.
433  *
434  * The @c name and @c nblock parameters are copied, but the data are not.
435  */
436 template <class T>
437 template <class U, class V>
438 // cppcheck-suppress uninitMemberVar ; false positive
439 ArenaHeapSTLAllocator<T, T>::ArenaHeapSTLAllocator
440  (const ArenaHeapSTLAllocator<U, V>& a)
441  : m_nblock (a.nblock()),
442  m_name (a.name()),
443  m_poolptr (a.poolptr())
444 {
445 }
446 
447 
448 /**
449  * @brief Return the hinted number of objects allocated per block.
450  */
451 template <class T>
452 inline
453 size_t ArenaHeapSTLAllocator<T, T>::nblock() const
454 {
455  return m_nblock;
456 }
457 
458 
459 /**
460  * @brief Return the name of this allocator.
461  */
462 template <class T>
463 inline
464 const std::string& ArenaHeapSTLAllocator<T, T>::name() const
465 {
466  return m_name;
467 }
468 
469 
470 /**
471  * @brief Return the statistics block for this allocator.
472  */
473 template <class T>
474 ArenaAllocatorBase::Stats
475 ArenaHeapSTLAllocator<T, T>::stats() const
476 {
477  if (m_poolptr)
478  return m_poolptr->stats();
479  return ArenaAllocatorBase::Stats();
480 }
481 
482 
483 /**
484  * @brief Return a pointer to the underlying allocator (may be 0).
485  */
486 template <class T>
487 const ArenaBlockAllocatorBase* ArenaHeapSTLAllocator<T, T>::poolptr() const
488 {
489  return m_poolptr;
490 }
491 
492 
493 //****************************************************************************
494 // Non-const variant.
495 //
496 
497 
498 /**
499  * @brief Constructor.
500  * @param a Allocator to reference.
501  * @param poolptr_nc Non-const pointer to the underlying allocator.
502  */
503 template <class T>
504 template <class U, class V>
505 ArenaNonConstHeapSTLAllocator<T>::ArenaNonConstHeapSTLAllocator
506  (const ArenaHeapSTLAllocator<U, V>& a,
507  ArenaBlockAllocatorBase* poolptr_nc)
508  : ArenaHeapSTLAllocator<T, T>(a),
509  m_poolptr_nc (poolptr_nc)
510 {
511 }
512 
513 
514 /**
515  * @brief Free all allocated elements.
516  *
517  * All elements allocated are returned to the free state.
518  * @c clear should be called on them if it was provided.
519  * The elements may continue to be cached internally, without
520  * returning to the system.
521  */
522 template <class T>
523 void ArenaNonConstHeapSTLAllocator<T>::reset()
524 {
525  if (m_poolptr_nc)
526  m_poolptr_nc->reset();
527 }
528 
529 
530 /**
531  * @brief Free all allocated elements and release memory back to the system.
532  *
533  * All elements allocated are freed, and all allocated blocks of memory
534  * are released back to the system.
535  * @c destructor should be called on them if it was provided
536  * (preceded by @c clear if provided and @c mustClear was set).
537  */
538 template <class T>
539 void ArenaNonConstHeapSTLAllocator<T>::erase()
540 {
541  if (m_poolptr_nc)
542  m_poolptr_nc->erase();
543 }
544 
545 
546 /**
547  * @brief Set the total number of elements cached by the allocator.
548  * @param size The desired pool size.
549  *
550  * This allows changing the number of elements that are currently free
551  * but cached. Any allocated elements are not affected by this call.
552  *
553  * If @c size is greater than the total number of elements currently
554  * cached, then more will be allocated. This will preferably done
555  * with a single block, but that is not guaranteed; in addition, the
556  * allocator may allocate more elements than is requested.
557  *
558  * If @c size is smaller than the total number of elements currently
559  * cached, as many blocks as possible will be released back to the system.
560  * It may not be possible to release the number of elements requested;
561  * this should be implemented on a best-effort basis.
562  */
563 template <class T>
564 void ArenaNonConstHeapSTLAllocator<T>::reserve (size_t size)
565 {
566  if (m_poolptr_nc)
567  m_poolptr_nc->reserve (size);
568 }
569 
570 
571 /**
572  * @brief Write-protect the memory managed by this allocator.
573  *
574  * Adjust protection on the memory managed by this allocator
575  * to disallow writes.
576  */
577 template <class T>
578 inline
579 void ArenaNonConstHeapSTLAllocator<T>::protect()
580 {
581  if (m_poolptr_nc)
582  m_poolptr_nc->protect();
583 }
584 
585 
586 /**
587  * @brief Write-enable the memory managed by this allocator.
588  *
589  * Adjust protection on the memory managed by this allocator
590  * to allow writes.
591  */
592 template <class T>
593 inline
594 void ArenaNonConstHeapSTLAllocator<T>::unprotect()
595 {
596  if (m_poolptr_nc)
597  m_poolptr_nc->unprotect();
598 }
599 
600 
601 /**
602  * @brief Return an allocator supporting non-const methods from
603  * a non-const container reference.
604  * @param c The (non-const) container.
605  */
606 template <class T>
607 template <class CONT>
608 ArenaNonConstHeapSTLAllocator<T>
609 ArenaHeapSTLAllocator<T, T>::get_allocator ATLAS_NOT_CONST_THREAD_SAFE (CONT& c)
610 {
611  // Must be called with a non-const object.
612  typename std::remove_const<CONT>::type& cc = c;
613  ArenaHeapSTLAllocator<T, T> a (cc.get_allocator());
614  return ArenaNonConstHeapSTLAllocator<T> (a,
615  const_cast<ArenaBlockAllocatorBase*>(a.poolptr()));
616 }
617 
618 
619 /**
620  * @brief Hook for unprotecting an arena.
621  *
622  * Sometimes we need to ensure that an arena is unprotected before we start
623  * destroying an object that contains the arena. To do that without
624  * making assumptions about whether the arena supports an unprotect
625  * operation, call this function.
626  */
627 template <class T, class VETO>
628 void maybeUnprotect (ArenaHeapSTLAllocator<T, VETO>& a)
629 {
630  a.unprotect();
631 }
632 
633 
634 } // namespace SG