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