ATLAS Offline Software
Loading...
Searching...
No Matches
ArenaHeapAllocator.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
11
15#include <vector>
16#include <algorithm>
17#include <cassert>
18
19
20namespace SG {
21
22
28ArenaHeapAllocator::ArenaHeapAllocator (const Params& params)
29 : ArenaBlockAllocatorBase (params),
30 m_freeptr (nullptr)
31{
32 // Consistency check.
33 assert (params.linkOffset + sizeof (pointer) <= params.eltSize);
34}
35
36
40ArenaHeapAllocator::~ArenaHeapAllocator()
41{
42 if (m_protected) {
43 try {
44 unprotect();
45 }
46 catch (const SG::ExcProtection&) {
47 // Got an error from mprotect...
48 std::abort();
49 }
50 }
52}
53
54
58ArenaHeapAllocator::ArenaHeapAllocator
59 (ArenaHeapAllocator&& other)
60 : ArenaBlockAllocatorBase (std::move (other)),
61 m_freeptr (other.m_freeptr)
62{
63 // False positives
64 // cppcheck-suppress useInitializationList
65 other.m_freeptr = nullptr;
66}
67
68
72ArenaHeapAllocator&
73ArenaHeapAllocator::operator=
74 (ArenaHeapAllocator&& other)
75{
76 if (this != &other) {
77 ArenaBlockAllocatorBase::operator= (std::move (other));
78 m_freeptr = other.m_freeptr;
79 other.m_freeptr = nullptr;
80 }
81 return *this;
82}
83
84
88void ArenaHeapAllocator::swap (ArenaHeapAllocator& other)
89{
90 if (this != &other) {
91 ArenaBlockAllocatorBase::swap (other);
92 std::swap (m_freeptr, other.m_freeptr);
93 }
94}
95
96
105void ArenaHeapAllocator::reset()
106{
107 if (!m_blocks) return;
108 if (m_params.clear) {
109 if (m_params.canReclear || m_freeptr == nullptr) {
110 // Just call clear() on all blocks --- allocated or not.
111 ArenaBlock::applyList (m_blocks, m_params.clear, m_blocks->size());
112 }
113 else {
114 // We can only call clear() on allocated blocks.
115 slowClear();
116 }
117 }
118
119 // Move all blocks back to the free list.
120 ArenaBlock::appendList (&m_freeblocks, m_blocks);
121
122 // Reset state.
123 m_blocks = nullptr;
124 m_freeptr = nullptr;
125 m_stats.elts.inuse = 0;
126 m_stats.blocks.free += m_stats.blocks.inuse;
127 m_stats.blocks.inuse = 0;
128}
129
130
139void ArenaHeapAllocator::erase()
140{
141 ArenaBlockAllocatorBase::erase();
142 m_freeptr = nullptr;
143}
144
145
149ArenaHeapAllocator::pointer ArenaHeapAllocator::refill()
150{
151 // Get a new block.
152 ArenaBlock* newblock = getBlock();
153
154 // Set up the links for the new free elements.
155 pointer lastelt = nullptr;
156 size_t sz = newblock->size();
157 size_t elt_size = newblock->eltSize();
158 for (size_t i=1; i < sz; i++) {
159 pointer elt = newblock->index (i, elt_size);
160 link(elt) = lastelt;
161 lastelt = elt;
162 }
163 // Set the free pointer to the next-to-last one.
164 m_freeptr = newblock->index (sz-1, elt_size);
165
166 // And return the last one.
167 return newblock->index (0, elt_size);
168}
169
170
174void ArenaHeapAllocator::slowClear()
175{
176 // Make a list of all free elements, in sorted order.
177 std::vector<pointer> free_ptrs;
178 free_ptrs.reserve (m_stats.elts.total - m_stats.elts.inuse);
179 for (pointer p = m_freeptr; p; p = link(p)) {
180 free_ptrs.push_back (p);
181 }
182 std::sort (free_ptrs.begin(), free_ptrs.end());
183
184 // Make a list of all used blocks, in sorted order.
185 std::vector<ArenaBlock*> blocks;
186 for (ArenaBlock* p = m_blocks; p; p = p->link()) {
187 blocks.push_back (p);
188 }
189 std::sort (blocks.begin(), blocks.end());
190
191 // Walk through both of these lists.
192 // For each block, walk through its elements, and call @c clear
193 // for those not on the free list.
194 std::vector<pointer>::iterator pi = free_ptrs.begin();
195 std::vector<pointer>::iterator pi_end = free_ptrs.end();
196 std::vector<ArenaBlock*>::iterator bi = blocks.begin();
197 std::vector<ArenaBlock*>::iterator bi_end = blocks.end();
198 func_t* clear = m_params.clear;
199 for (; bi != bi_end; ++bi) {
200 ArenaBlock& bl = **bi;
201 size_t sz = bl.size();
202 size_t elt_size = bl.eltSize();
203 for (size_t i = 0; i < sz; i++) {
204 pointer ptr = bl.index (i, elt_size);
205 if (pi != pi_end && ptr == *pi) {
206 ++pi;
207 }
208 else {
209 //'clear' is checked for validity by the caller
210 //coverity[NULL_FIELD:FALSE]
211 clear (ptr);
212 }
213 }
214 }
215}
216
217
218} // namespace SG
A large memory block that gets carved into smaller uniform elements. See Arena.h for an overview of t...
Heap-based allocator. See Arena.h for an overview of the arena-based memory allocators.
Exceptions that can be thrown from AthAllocators.
static Double_t sz
void clear()
Empty the pool.
#define pi
Common functionality for block-oriented allocators.
void eraseUnprotected()
Free all allocated elements and release memory back to the system.
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.
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.
Exception — Attempt to change memory protection failed.
Forward declaration.
pointer m_freeptr
Pointer to the next free element.
void slowClear()
Call clear() for all allocated elements.
pointer & link(pointer p) const
Return a reference to the link for an element.
ArenaHeapAllocator(const Params &params)
Constructor.
STL namespace.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)