ATLAS Offline Software
Loading...
Searching...
No Matches
ArenaPoolAllocator.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
11
15#include <cassert>
16
17
18namespace SG {
19
20
26inline
29 ArenaBlock* & block)
30{
31 // If we haven't yet reached the start of this block, move the iterator
32 // back one.
33 if (base > block->index(0,0)) {
34 return base - block->eltSize();
35 }
36
37 // Move to the previous block.
38 block = block->link();
39 if (block) {
40 return block->index (block->size()-1, block->eltSize());
41 }
42 return nullptr;
43}
44
45
51inline
54 const ArenaBlock* & block)
55{
56 // If we haven't yet reached the start of this block, move the iterator
57 // back one.
58 if (base > block->index(0,0)) {
59 return base - block->eltSize();
60 }
61
62 // Move to the previous block.
63 block = block->link();
64 if (block) {
65 return block->index (block->size()-1, block->eltSize());
66 }
67 return nullptr;
68}
69
70
75{
76 this->base_reference() =
77 ArenaPoolAllocator_iterator_increment (this->base_reference(), m_block);
78}
79
80
90
91
99 m_ptr (nullptr),
100 m_end (nullptr)
101{
102}
103
104
109{
110 if (m_protected) {
111 try {
112 unprotect();
113 }
114 catch (const SG::ExcProtection&) {
115 // Got an error from mprotect...
116 std::abort();
117 }
118 }
120}
121
122
127 (ArenaPoolAllocator&& other)
128 : ArenaBlockAllocatorBase (std::move (other)),
129 m_ptr (other.m_ptr),
130 m_end (other.m_end)
131{
132 // False positives
133 // cppcheck-suppress useInitializationList
134 other.m_ptr = nullptr;
135 // cppcheck-suppress useInitializationList
136 other.m_end = nullptr;
137}
138
139
144ArenaPoolAllocator::operator=
145 (ArenaPoolAllocator&& other)
146{
147 if (this != &other) {
148 ArenaBlockAllocatorBase::operator= (std::move (other));
149 m_ptr = other.m_ptr;
150 m_end = other.m_end;
151 other.m_ptr = nullptr;
152 other.m_end = nullptr;
153 }
154 return *this;
155}
156
157
162{
163 if (this != &other) {
165 std::swap (m_ptr, other.m_ptr);
166 std::swap (m_end, other.m_end);
167 }
168}
169
170
180{
181 // Clear each block in turn.
182 while (m_blocks) {
183 clearBlock();
184 }
185
186 // Check that things are consistent.
187 assert (m_stats.elts.inuse == 0);
188 assert (m_ptr == nullptr);
189 assert (m_end == nullptr);
190}
191
192
202{
203 // Delete all the blocks.
205
206 // Reset pointers.
207 m_ptr = m_end = nullptr;
208}
209
210
219{
220 // Clear the topmost block, as long as it doesn't contain the sought-after
221 // pointer.
222 ArenaBlock* p = m_blocks;
223 assert (p != nullptr);
224 size_t elt_size = p->eltSize();
225 while (p && !(blk >= p->index(0, elt_size) &&
226 blk < p->index(p->size(), elt_size)))
227 {
228 clearBlock();
229 p = m_blocks;
230 }
231
232 // We'll trip this if the supplied pointer wasn't in any block.
233 assert (p != nullptr);
234
235 // If the element is at the beginning of this block, just clear the whole
236 // thing.
237 if (blk == p->index(0, elt_size)) {
238 clearBlock();
239 }
240 else {
241 // Otherwise, we need to clear some of the elements in this block.
242 // See if we need to call @c clear.
243 func_t* clear = m_params.clear;
244 if (clear) {
245 // Yeah, we do. Call @c clear on each element in turn.
246 while (m_ptr > blk) {
247 m_ptr -= elt_size;
248 clear (m_ptr);
249 --m_stats.elts.inuse;
250 }
251 // We'll trip this if the supplied pointer wasn't on an element
252 // boundary.
253 assert (m_ptr == blk);
254 }
255 else {
256 // We don't need to call @c clear.
257 // So we can do it the fast way --- just reset pointers.
258 m_stats.elts.inuse -= (m_ptr - blk) / elt_size;
259 m_ptr = blk;
260 }
261 }
262}
263
264
272{
273 // If @c m_ptr is one set, it is one more than the last allocated element.
274 return iterator (m_ptr ? m_ptr - m_params.eltSize : nullptr, m_blocks);
275}
276
277
285{
286 // If @c m_ptr is one set, it is one more than the last allocated element.
287 return const_iterator (m_ptr ? m_ptr - m_params.eltSize : nullptr, m_blocks);
288}
289
290
295{
296 // Use a null iterator to signal the end.
297 return iterator ();
298}
299
300
305{
306 // Use a null iterator to signal the end.
307 return const_iterator ();
308}
309
310
315{
316 // Get a new block.
317 ArenaBlock* newblock = getBlock();
318
319 // Set the pointers.
320 m_ptr = newblock->index (0, m_params.eltSize);
321 m_end = newblock->index (newblock->size(), m_params.eltSize);
322}
323
324
330{
331 // The topmost block.
332 ArenaBlock* p = m_blocks;
333
334 // Nothing to do if there are no allocated blocks!
335 if (!p) return;
336
337 size_t elt_size = p->eltSize();
338
339 // The first element of the block.
340 pointer base = p->index(0, elt_size);
341
342 // Do we need to call @c clear? If so, call it on all allocated elements
343 // in this block.
344 func_t* clear = m_params.clear;
345 if (clear) {
346 pointer elt = base;
347 while (elt < m_ptr) {
348 clear (elt);
349 elt += elt_size;
350 }
351 }
352
353 // Update statistics.
354 --m_stats.blocks.inuse;
355 ++m_stats.blocks.free;
356 m_stats.elts.inuse -= (m_ptr - base) / elt_size;
357
358 // Move the block from the allocated to the free list.
359 m_blocks = p->link();
360 p->link() = m_freeblocks;
361 m_freeblocks = p;
362 p = m_blocks;
363
364 // Reset the pointers.
365 if (p) {
366 m_ptr = m_end = p->index(p->size());
367 }
368 else {
369 m_ptr = m_end = nullptr;
370 }
371}
372
373
374} // namespace SG
A large memory block that gets carved into smaller uniform elements. See Arena.h for an overview of t...
Pool-based allocator. See Arena.h for an overview of the arena-based memory allocators.
Exceptions that can be thrown from AthAllocators.
char * pointer
Type for pointers to elements.
void func_t(pointer)
Type of functions for constructor, etc.
const char * const_pointer
And a const version of the pointer.
void unprotect()
Write-enable the memory managed by this allocator.
const Params & params() const
Return this Allocator's parameters.
ArenaBlock * getBlock()
Return an empty block, either newly-allocated or from the free list.
ArenaBlockAllocatorBase & operator=(const ArenaBlockAllocatorBase &)=delete
virtual void erase() override
Free all allocated elements and release memory back to the system.
void eraseUnprotected()
Free all allocated elements and release memory back to the system.
ArenaAllocatorBase::Stats m_stats
The statistics structure.
void swap(ArenaBlockAllocatorBase &other)
Swap.
ArenaBlockAllocatorBase(const Params &params)
Constructor.
ArenaBlock * m_blocks
The list of blocks currently in use.
Params m_params
The parameters for this allocator.
ArenaBlock * m_freeblocks
The list of free blocks.
bool m_protected
Flag whether the arena has been protected.
A large memory block that gets carved into smaller uniform elements.
Definition ArenaBlock.h:43
pointer index(size_t i)
Return a pointer to element i in the block.
ArenaBlock *& link()
Return the link pointer of the block.
size_t eltSize() const
Return the size of the elements in the block.
size_t size() const
Return the number of elements in the block.
const ArenaBlock * m_block
Block containing the current element.
void increment()
Move the iterator forward.
Non-const iterator for the pool.
void increment()
Move the iterator forward.
ArenaBlock * m_block
Block containing the current element.
Pool-based allocator.
pointer m_end
One past the last available element in the current block, of null.
iterator begin()
Starting pool iterator.
virtual void reset() override
Free all allocated elements.
void resetTo(pointer p)
Reset pool back to a previous state.
void refill()
Add more free elements to the pool.
void clearBlock()
Reset all elements in the topmost block, and move the block to the free list.
virtual ~ArenaPoolAllocator()
Destructor.
pointer m_ptr
Pointer to the next free element to allocate, or null.
ArenaPoolAllocator(const Params &params)
Constructor.
void swap(ArenaPoolAllocator &other)
Swap.
virtual void erase() override final
Free all allocated elements and release memory back to the system.
iterator end()
Ending pool iterator.
Exception — Attempt to change memory protection failed.
std::string base
Definition hcg.cxx:81
Forward declaration.
ArenaPoolAllocator::pointer ArenaPoolAllocator_iterator_increment(ArenaPoolAllocator::pointer base, ArenaBlock *&block)
Helper: common code for advancing an iterator.
Definition index.py:1
STL namespace.
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)