ALib C++ Library
Library Version: 2511 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
poolallocator.inl
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header-file is part of module \alib_monomem of the \aliblong.
4///
5/// \emoji :copyright: 2013-2025 A-Worx GmbH, Germany.
6/// Published under \ref mainpage_license "Boost Software License".
7//==================================================================================================
8ALIB_EXPORT namespace alib { namespace monomem {
9
10#if !defined(ALIB_MONOMEM_POOLALLOCATOR_DEFAULT_ALIGNMENT)
11# define ALIB_MONOMEM_POOLALLOCATOR_DEFAULT_ALIGNMENT alignof(uint64_t)
12#endif
13
14//==================================================================================================
15/// \par Important Note
16/// Please consult the \ref alib_contmono_intro "Programmer's Manual" of \alib module
17/// \alib_monomem_nl for an introduction into the rather complex topic of monotonous and
18/// pool allocation and how to use this class.
19///
20/// This class implements the interface prototyped with \alib{lang;Allocator}.
21/// Whenever an object is freed with this allocator, the memory is stored in a stack for later
22/// re-use. This means, with allocations, first it is checked if a previously freed object of
23/// fitting size is available, and only if not, new memory is allocated.
24/// To implement this in a performant way (preferably with compile-time calculations), the following
25/// approach was taken:
26/// - The size of every allocation request is increased to the next higher power of 2 bound.
27/// For example, if a memory piece of 42 bytes is requested, a piece of size 64 bytes is returned.
28/// - For each allocation size, a simple stack (single directed linked list) is used to dispose and
29/// recycle memory.
30/// - The minimum allocation size is <c>sizeof(void*)</c>, because for the recycling mechanism
31/// a pointer needs to be stored in the freed pool memory, when it is added to the internal
32/// "recycling stack".
33/// - This results in only 61 different allocation sizes (on a 64-bit machine).
34/// - A fixed alignment for all objects is used. This is also the maximum alignment allowed to pass
35/// to methods #allocate and #reallocate. Its value is defined by template parameter
36/// \p{TAlignment}, which defaults to what is given with the compiler-symbol
37/// \ref ALIB_MONOMEM_POOLALLOCATOR_DEFAULT_ALIGNMENT, which in turn defaults to
38/// <c>alignof(uint64_t)</c>.
39/// - This approach results in only 61 different allocation sizes (on a 64-bit machine).
40///
41/// The consequences of this strategy are straight forward:
42/// - Using this allocator type requires disposing (free) every allocated piece of memory (which is
43/// in contrast to \b MonoAllocator).
44/// - This type is well suited for allocation scenarios, which release each object within
45/// a certain period of time, just to allocate new ones shortly afterward. A good use
46/// case example is given with module \alib_threadmodel: Here, request objects are
47/// pushed into priority queues, which are disposed after the request got processed. The objects
48/// are rather small and of different sizes. In complex server scenarios, it can become quickly
49/// millions of messages per second which are created and disposed.
50/// - A statistical average of 25% memory allocation overhead (waste) is taken into account with
51/// the use of this class.
52///
53/// Chapter \ref alib_contmono_intro_recycling of the joint Programmer's Manual of modules
54/// \alib_containers_nl and \alib_monomem_nl provides an in-depth discussion of what is called
55/// "recycling" in this context. Several strategies are proposed with container types provided by
56/// module \alib_containers_nl. From this perspective, this allocator could be seen as a
57/// "recycling proxy" in front of a \b MonoAllocator (or a different,
58/// \ref alib_contmono_chaining "chained" allocator).
59///
60/// @see
61/// - The \ref alib_contmono_intro "Programmer's Manual" of module \alib_monomem_nl.
62/// - The "standard" type definition of this template type \alib{MonoAllocator},
63/// which uses an \alib{lang;HeapAllocator} as the
64/// \ref alib_contmono_chaining "chained allocator".
65///
66/// @tparam TAllocator The underlying allocator to use.<br>
67/// With type definition \alib{PoolAllocator},this is bound to type
68/// \alib{MonoAllocator}.<br>
69/// With type definition \alib{PoolAllocatorHA},this is bound to type
70/// \alib{lang;HeapAllocator}.<br>
71/// For general information see chapter \ref alib_contmono_chaining
72/// of the Programmer's Manual.
73/// @tparam TAlignment The fixed alignment to use. Corresponding method parameters are ignored.<br>
74/// Defaults to the compiler-symbol
75/// \ref ALIB_MONOMEM_POOLALLOCATOR_DEFAULT_ALIGNMENT, which in turn defaults
76/// to <c>alignof(uint64_t)</c>.<br>
77/// It is statically asserted that this value is not higher than
78/// field \alib{lang::Allocator;MAX_ALIGNMENT} of the given chained
79/// \p{TAllocator} and not smaller than <c>alignof(void*)</c>.<br>
80/// See Chapter \ref alib_contmono_further_alignment of the Programmer's Manual
81/// of this module.
82//==================================================================================================
83template<typename TAllocator, size_t TAlignment= ALIB_MONOMEM_POOLALLOCATOR_DEFAULT_ALIGNMENT>
84class TPoolAllocator : public lang::AllocatorMember<TAllocator>
85#if ALIB_DEBUG_CRITICAL_SECTIONS
87#endif
88{
89 static_assert( TAlignment >= alignof(void*),
90 "The (fixed) alignment of the pool allocator has to be at least as high as alignof(void*). "
91 "Adjust template parameter TAlignment." );
92
93 static_assert( TAlignment <= TAllocator::MAX_ALIGNMENT,
94 "The (fixed) alignment of the pool allocator cannot be greater than the MAX_ALIGNMENT of "
95 "its chained allocator. Adjust template parameter TAlignment." );
96
97 #if !defined(_WIN32) // not a constexpr under windows
98 static_assert(lang::BitCount(TAlignment) == 1,
99 "The fixed alignment of the pool allocator is not a power of 2. "
100 "Adjust template parameter TAlignment." );
101 #endif
102
103 /// A magic byte, used with the compiler-symbol \ref ALIB_DEBUG_ALLOCATIONS to mark
104 /// memory and detect out-of-bounds writes.
105 /// @see Method \alib{lang;Allocator::dbgCheckMemory}.
106 static constexpr unsigned char MAGIC= 0xA3;
107
108 /// A magic byte written when memory is freed.
109 /// @see Field #CLEAR.
110 static constexpr unsigned char CLEAR= 0xF3;
111
112 protected:
113
114 using allocMember= lang::AllocatorMember<TAllocator>; ///< A shortcut to a base type.
115
116 //============================================= Fields ===========================================
117 /// Array of hooks. Each hook points to previously disposed memory of the same size.
118 /// Its length is determined with \c constexpr #qtyHooks and it is allocated with construction
119 /// in \p{allocator}.
120 void** hooks = nullptr;
121
122 #if ALIB_DEBUG
123 public:
124 /// A name for this object.
125 /// The constructors grab this name from the chained allocator, which most often is an
126 /// already named \b MonoAllocator. Thus, no constructor argument is available
127 /// (in contrast to class \alib{monomem;TMonoAllocator;MonoAllocator}).
128 /// This name may be changed after construction by the using code as appropriate.
129 const char* DbgName;
130 protected:
131 #endif
132
133 #if ALIB_DEBUG_MEMORY
134 /// The overall number of allocations for each size.
136 #endif
137
138 #if ALIB_DEBUG_ALLOCATIONS
139 /// The current number of allocations that have not been freed.
140 int* dbgOpenAllocations = nullptr;
141
142 /// This member is used with \ref ALIB_DEBUG_ALLOCATIONS to pass the requested size from
143 /// interface methods to the implementation. While this approach is not thread-safe, it
144 /// avoids adding some method parameter, which would exist only in debug versions.
145 /// It was intentionally implemented like this, to cause testing errors in case that
146 /// multithreaded access was not locked against racing conditions properly by the user.
148 #endif
149
150 //======================================== Internal Methods ======================================
151 /// To be able to store allocated memory in the recycling stacks, any allocated memory is at
152 /// least of size <c>sizeof(void*)</c>. Hence sizes \c 1 and \c 2 (with 64-bit systems
153 /// also \c 4) will never be allocated and no hook is available for these sizes.
154 /// @return \c 3 on 64-bit systems, \c 2 on 32-bit systems.
155 static constexpr short minimumHookIndex() { return sizeof(size_t) == 4 ? 2 : 3; }
156
157
158 /// The number of hooks needed. Evaluates to \c 61 on a common 64-bit platform and \c 29 on a
159 /// @return \c 61 on 64-bit systems, \c 29 on 32-bit systems.
160 static constexpr short qtyHooks() { return short(bitsof(size_t)) - minimumHookIndex(); }
161
162 /// Calculates the index of the hook in field #hooks. This corresponds to the number
163 /// of the most significant bit in the next higher power of 2 value minus #minimumHookIndex.
164 /// @param requestedObjectSize The object size requested by the user.
165 /// @return The index of the recycler hook in #hooks.
166 static constexpr
167 short hookIndex(size_t requestedObjectSize) {
168 if( requestedObjectSize < sizeof(void*) )
169 return 0;
170 int msb= lang::MSB(requestedObjectSize);
171 return short( ((requestedObjectSize & lang::LowerMask<size_t>(msb-1) ) == 0 ? msb -1: msb )
172 - minimumHookIndex() );
173 }
174
175 /// Templated version of #hookIndex(size_t).
176 /// @tparam TRequestedObjectSize The object size requested by the user, hence excluding the
177 /// internal pointer.
178 /// @return The index of the recycler hook in #hooks.
179 template<size_t TRequestedObjectSize>
180 static constexpr
181 short hookIndex() {
182 if( TRequestedObjectSize < sizeof(void*) )
183 return 0;
184 constexpr int msb = lang::MSB(TRequestedObjectSize);
185 return short( ((TRequestedObjectSize & lang::LowerMask<msb-1, size_t>() ) == 0 ? msb-1 : msb)
186 - minimumHookIndex() );
187 }
188
189 /// Frees all recycled pool objects.
191
192 public:
193 /// The type of the allocator that this allocator uses underneath to allocate the buffers,
194 /// given with template parameter \p{TAllocator}.<br>
195 /// The instance can be accessed with inherited methods
196 /// \alib{lang::AllocatorMember;GetAllocator} and \alib{lang::AllocatorMember;AI}.
197 using ChainedAllocator = TAllocator;
198
199 /// Evaluates to the value of template parameter \p{TAlignment}.
200 /// @see Field \alib{lang;Allocator::MIN_ALIGNMENT}.
201 static constexpr size_t MIN_ALIGNMENT = TAlignment;
202
203 /// Evaluates to the value of template parameter \p{TAlignment}.
204 /// @see Field \alib{lang;Allocator::MAX_ALIGNMENT}.
205 static constexpr size_t MAX_ALIGNMENT = TAlignment;
206
207 //========================================== Construction ========================================
208 /// Constructs this type.
209 /// @param pAllocator The allocator to use for allocating pool objects.
211 TPoolAllocator ( TAllocator& pAllocator );
212
213 /// Constructs this type without a given allocator. This constructor is applicable only
214 /// if \p{TAllocator} is default-constructible (e.g., \alib{lang;HeapAllocator}).
215 /// @tparam TRequires Defaulted template parameter. Must not be specified.
216 template<typename TRequires= allocMember>
217 requires std::default_initializable<TRequires>
219 #if ALIB_DEBUG_CRITICAL_SECTIONS
220 :lang::DbgCriticalSections("PoolAllocator")
221 #endif
222 {
223 #if defined(_WIN32) // otherwise statically asserted in header
224 ALIB_ASSERT_ERROR(lang::BitCount(TAlignment) == 1, "MONOMEM",
225 "The fixed alignment {} of the pool allocator is not a power of 2. "
226 "Adjust template parameter TAlignment.", TAlignment )
227 #endif
228
230
231 // allocate and initialize hook array
232 hooks= allocMember::AI().template AllocArray<void*>(qtyHooks() );
233 std::memset( hooks, 0, sizeof( void*[qtyHooks()] ) );
234 #if ALIB_DEBUG_ALLOCATIONS
235 dbgOpenAllocations= allocMember::AI().template AllocArray<int>(qtyHooks() );
236 std::memset( dbgOpenAllocations, 0, sizeof( int[qtyHooks()] ) );
237 #endif
238 #if ALIB_DEBUG_MEMORY
239 dbgStatAllocCounter= allocMember::AI().template AllocArray<uinteger>(qtyHooks() );
240 std::memset( dbgStatAllocCounter, 0, sizeof( uinteger[qtyHooks()] ) );
241 #endif
242 }
243
244 /// Destructs this type.
247
248 //##############################################################################################
249 /// @name lang::Allocator Implementation
250 //##############################################################################################
251 /// Allocates or re-uses a previously freed piece of memory of equal \p{size}.
252 /// Any given \p{size} is rounded up to the next higher power of 2 before comparison and
253 /// returned via in/output parameter \p{size}.
254 /// @param[in,out] size The size of memory the block to allocate in bytes. This will be rounded
255 /// up to the next higher power of 2 when the function returns.
256 /// Any additional size might be used by the caller.
257 /// @param pAlignment The (minimum) alignment of the memory block to allocate in bytes.
258 /// This is ignored with this allocator. Instead, it uses what is specified
259 /// by template parameter \p{TAlignment}.
260 /// See Chapter \ref alib_contmono_further_alignment of the Programmer's
261 /// Manual of this module.
262 /// @return Pointer to the allocated memory.
263 void* allocate( size_t& size, size_t pAlignment ) {
264 ALIB_ASSERT_ERROR(pAlignment <= TAlignment, "MONOMEM",
265 "The requested alignment is higher than what was specified with "
266 "template parameter TAlignment: {} >= {}", pAlignment, TAlignment )
267 (void) pAlignment;
268
269 #if ALIB_DEBUG_ALLOCATIONS
271 #endif
272
273 short allocInfo= GetAllocInformation(size);
274 size= GetAllocationSize(allocInfo);
275 return AllocateByAllocationInfo(allocInfo);
276 }
277
278 /// Shrinks or grows a piece of memory. If a new allocation was performed the existing
279 /// data is copied. Any given \p{oldSize} and \p{newSize} is rounded up to the next higher
280 /// power of 2 before comparison. Note, that parameter \p{newSize} is provided as a reference.
281 /// @param mem The memory to reallocate.
282 /// @param oldSize The current size of \p{mem}.
283 /// @param[in,out] newSize The size of memory the block to allocate in bytes. This will be rounded
284 /// up to the next higher power of 2 when the function returns. Any
285 /// additional size might be used by the caller.
286 /// @param pAlignment The (minimum) alignment of the memory to allocate in bytes.
287 /// This is ignored with this allocator. Instead, it uses what is
288 /// specified by template parameter \p{TAlignment}.
289 /// See Chapter \ref alib_contmono_further_alignment of the Programmer's
290 /// Manual of this module.
291 /// @return Pointer to the re-allocated memory.
292 void* reallocate( void* mem, size_t oldSize, size_t& newSize, size_t pAlignment );
293
294 /// Disposes the given memory. The fragment is stored for later reuse with method #allocate
295 /// of memory sizes of the same power of 2 range.
296 ///
297 /// @param mem The memory to dispose.
298 /// @param size The size of the given \p{mem}.
299 void free(void* mem, size_t size) {
300 #if ALIB_DEBUG_ALLOCATIONS
302 #endif
303 FreeByAllocationInfo( hookIndex(size), mem );
304 }
305
306 /// For an explanation, see \alib{lang;Allocator::dbgAcknowledgeIncreasedAllocSize}.
307 /// @tparam TSize The type of parameter \p{allocSize}. (Deduced by the compiler.)
308 /// @param mem The address of the allocated object.
309 /// @param allocSize The true allocation size returned by the method #allocate .
310 template<typename TSize>
311 void dbgAcknowledgeIncreasedAllocSize( void* mem, TSize allocSize ) const
312 { lang::DbgAlloc::annotate(mem, allocSize, MAGIC); }
313
314 #if DOXYGEN
315 /// See the description of this method with prototype \alib{lang;Allocator::allowsMemSplit}.<br>
316 /// (Note: This method is static. For technical reasons this cannot be reflected in this
317 /// documentation)
318 /// @return \c false.
319 constexpr bool allowsMemSplit() noexcept;
320 #else
321 static constexpr bool allowsMemSplit() noexcept { return false; }
322 #endif
323
324 /// Returns a temporary object (which is usually optimized out together with a call to this
325 /// operator) providing high-level convenience methods for allocation.
326 /// @see Class \alib{lang::AllocatorInterface}
327 /// @return A temporary high-level interface into the allocator.
330
331 //##############################################################################################
332 /// @name Specific Interface (Static Methods)
333 //##############################################################################################
334 /// Returns the number of relevant bits of the allocation information value returned by
335 /// overloaded methods #GetAllocInformation. In other words, the value returned by these
336 /// methods is between \c 0 and the power of 2 of the value returned by this method.
337 /// @return \c 5 on 32-bit systems and \c 6 on 64 bit systems.
338 /// #GetAllocInformation.
339 static constexpr
340 int AllocationInformationBitCount() { return bitsof(void*) == 32 ? 5 : 6; }
341
342 /// This static \c constexpr method returns information that this allocator needs for allocation
343 /// and freeing of objects. In the case that the original allocation type is not known on
344 /// deletion (e.g., if virtual destructors are used), then this piece of information has to be
345 /// collected with this function (probably on construction) and provided to
346 /// #FreeByAllocationInfo via custom mechanics.
347 ///
348 /// \note
349 /// Two options are quite obvious to implement:
350 /// 1. The information is stored within the object and passed on destruction.
351 /// 2. The information is retrieved from a virtual function, which is implemented using this
352 /// \c constexpr type.
353 /// \note
354 /// While the second version has a small impact on code size and execution speed
355 /// (because the virtual function has to be called with deletion), the first version
356 /// increases the footprint of the object. So both approaches have their advantages and
357 /// disadvantages.<br><br>
358 /// \note
359 /// A third option is explained in a step-by-step sample in chapter
360 /// \ref alib_contmono_poolallocator_metatrick of the Programmer's Manual of this module.
361 ///
362 /// Technically, the returned value is the exponent base 2 of the next higher power of 2
363 /// value, minus the minimum supported exponent. This directly gives an index into field
364 /// #hooks.
365 /// @tparam T The object type that allocation information is to be retrieved for.
366 /// @return Allocation information.
367 template<typename T>
368 static constexpr short GetAllocInformation() { return hookIndex<sizeof(T)>(); }
369
370 /// Same as the templated #GetAllocInformation<T>() version, but accepts method parameter
371 /// \p{size} instead of a template parameter.
372 /// Thus, this version is only potentially \c constexpr.
373 ///
374 /// @tparam TIntegral The type that parameter \p{size} is provided with. If not integral,
375 /// this method is not chosen by the compiler.
376 /// @param size The size of the object to be allocated or disposed in a probalble next step.
377 /// @return Allocation information. See #GetAllocInformation<T>().
378 template<typename TIntegral>
379 requires std::integral<TIntegral>
380 static constexpr short GetAllocInformation(TIntegral size) { return hookIndex(size_t(size)); }
381
382 /// Returns the allocation size for a value returned by #GetAllocInformation.
383 ///
384 /// @param allocInfo The alloc information received with #GetAllocInformation.
385 /// @return The next higher power of 2 in respect to the size passed as parameter to
386 /// #GetAllocInformation.
387 static constexpr size_t GetAllocationSize(short allocInfo)
388 { return size_t(1)<<(allocInfo + minimumHookIndex()); }
389
390 //##############################################################################################
391 /// @name Specific Interface
392 //##############################################################################################
393 /// Allocates or recycles previously freed memory suitable to emplace an instance with the
394 /// given allocation information.
395 /// \note This method is to be used in combination with template method #GetAllocInformation
396 /// in situations, where the type information of the allocation is not available
397 /// or has to be transferred to a non-templated library function or similar.
398 /// @param allocInfo The allocation information received with #GetAllocInformation.
399 /// @return A pointer to the allocated memory.
401 void* AllocateByAllocationInfo(int allocInfo);
402
403
404 /// Disposes an object (or piece of memory) which has been allocated using
405 /// #AllocateByAllocationInfo.
406 /// If the compiler-symbol \ref ALIB_DEBUG_ALLOCATIONS is set, the method will overwrite the freed
407 /// memory with character <c>0xD3</c>.
408 /// @param allocInfo The allocation information received with #GetAllocInformation.
409 /// @param mem The object to dispose.
410 void FreeByAllocationInfo(int allocInfo, void* mem ) {ALIB_DCS
411 #if ALIB_DEBUG_ALLOCATIONS
412 // if not set, then this method had been called directly from outside and we expect
413 // that the hook index is stored instead of the true requested size.
414 if( dbgLastRequestedSize == 0 )
415 dbgLastRequestedSize= (size_t(1) << (allocInfo + minimumHookIndex()));
418 lang::DbgAlloc::clearMem( mem, size_t(1) << (allocInfo + minimumHookIndex()), MAGIC );
419 --dbgOpenAllocations[allocInfo];
420 #endif
421
422 *reinterpret_cast<void**>(mem)= hooks[allocInfo];
423 hooks[allocInfo]= mem;
424 }
425
426 /// Deletes all current pool objects with the #ChainedAllocator.
427 /// The state of this class equals the state after construction.
428 void Reset() {
429 deletePool();
430 std::memset( hooks, 0, sizeof( void*[qtyHooks()] ) );
431 #if ALIB_DEBUG_ALLOCATIONS
432 std::memset( dbgOpenAllocations, 0, sizeof( int[qtyHooks()] ) );
433 #endif
434 #if ALIB_DEBUG_MEMORY
435 std::memset( dbgStatAllocCounter, 0, sizeof( uinteger[qtyHooks()] ) );
436 #endif
437
438 }
439
440 /// Returns the number of available pool objects, hence those that had been allocated,
441 /// freed, and not been reused with a next allocation again.
442 /// @param size The size of the object requested, as given with #allocate and #free.
443 /// @return The number of pool objects of the given size.
445 integer GetPoolSize(size_t size);
446
447 /// If the compiler-symbol \ref ALIB_DEBUG_ALLOCATIONS is not set, this method is empty and will
448 /// be optimized out. Otherwise, this will raise an \alib_assertion if the piece of allocated
449 /// memory is corrupted or its allocation size is not rightfully given by the using code.
450 /// @see Chapter \ref alib_contmono_further_debug of the Programmer's Manual.
451 ///
452 /// @tparam TSize The type of parameter \p{size}. (Deduced by the compiler.)
453 /// @param mem The address of the allocated object.
454 /// @param size The requested allocation size of the object.
455 template<typename TSize>
456 void dbgCheckMemory( void* mem, TSize size )
457 { lang::DbgAlloc::checkMem( mem, size, MAGIC, ALIB_REL_DBG(nullptr, DbgName)); }
458
459 #if ALIB_DEBUG_ALLOCATIONS
460 /// Returns the number of objects of the given \p{size} currently allocated (and not freed).<br>
461 /// Only functional if the compiler-symbol \ref ALIB_DEBUG_ALLOCATIONS is set.
462 /// Otherwise, this is a <c>static constexpr</c> function that returns \c 0.
463 /// @see Overloaded method #DbgCountedOpenAllocations() which returns the overall number.
464 /// @param size The size of the object requested, as given with #allocate and #free.
465 /// @return The number of non-freed allocations.
467 {
468 return dbgOpenAllocations[hookIndex(size)];
469 }
470
471 /// Returns the number of objects currently allocated (and not freed).<br>
472 /// Only functional if the compiler-symbol \ref ALIB_DEBUG_ALLOCATIONS is set.
473 /// Otherwise, this is a <c>static constexpr</c> function that returns \c 0.
474 /// @return The number of non-freed allocations.
476 {
477 int result= 0;
478 for(int i= 0; i < qtyHooks(); ++i)
479 result+= dbgOpenAllocations[i];
480 return result;
481 }
482
483 /// Actively suppresses a warning on destruction in case #DbgCountedOpenAllocations does not
484 /// return \c 0.<br>
485 /// Only functional if the compiler-symbol \ref ALIB_DEBUG_ALLOCATIONS is set.
486 /// Otherwise, this is a <c>static constexpr</c> function that returns \c 0.
487 /// @return The number of non-freed allocations.
489 {
490 int result= DbgCountedOpenAllocations();
491 std::memset( dbgOpenAllocations, 0, sizeof( int[qtyHooks()] ) );
492 return result;
493 }
494
495 #else
496 static constexpr int DbgCountedOpenAllocations(size_t ) { return 0; }
497 static constexpr int DbgCountedOpenAllocations() { return 0; }
498 static constexpr int DbgSuppressNonFreedObjectsWarning() { return 0; }
499 #endif
500
501 #if ALIB_DEBUG_MEMORY
502 /// Returns the overall number of allocated (and potentially freed) objects of the given
503 /// \p{size}.<br>
504 /// Only functional if the compiler-symbol \ref ALIB_DEBUG_MEMORY is set.
505 /// Otherwise, this is a <c>static constexpr</c> function that returns \c 0.
506 /// @see Overloaded method #DbgStatAllocCounter() which returns the overall number.
507 /// @param size The size of the object requested, as given with #allocate and #free.
508 /// @return The number of non-freed allocations.
510 {
511 return dbgStatAllocCounter[hookIndex(size)];
512 }
513
514 /// Returns the overall number of objects currently allocated (and not freed).<br>
515 /// Only functional if the compiler-symbol \ref ALIB_DEBUG_MEMORY is set.
516 /// Otherwise, this is a <c>static constexpr</c> function that returns \c 0.
517 /// @return The number of non-freed allocations.
519 {
520 uinteger result= 0;
521 for(int i= 0; i < qtyHooks(); ++i)
522 result+= dbgStatAllocCounter[i];
523 return result;
524 }
525
526 #else
527 static constexpr uinteger DbgStatAllocCounter(size_t) { return 0; }
528 static constexpr uinteger DbgStatAllocCounter() { return 0; }
529 #endif
530}; // class TPoolAllocator
531
532
533#if !DOXYGEN
536#endif
537
538} // namespace alib[::monomem]
539
540/// Type alias in namespace \b alib.
541/// This alias fixes template parameter \p{TAllocator} (which defines the
542/// \ref alib_contmono_chaining "chained allocator") to type alias #alib::MonoAllocator, which
543/// in turn defines its chained allocator to type \alib{lang;HeapAllocator}.
545
546/// Type alias in namespace \b alib.
547/// This alias fixes template parameter \p{TAllocator} (which defines the
548/// \ref alib_contmono_chaining "chained allocator") to type \alib{lang;HeapAllocator}.
550
551/// Type alias in namespace \b alib to denote the use of a
552/// \alib{PoolAllocator} with type \alib{lang::StdAllocator}.
553template<typename T>
555
556} // namespace [alib]
void FreeByAllocationInfo(int allocInfo, void *mem)
static constexpr short qtyHooks()
uinteger DbgStatAllocCounter(size_t size)
void dbgAcknowledgeIncreasedAllocSize(void *mem, TSize allocSize) const
void dbgCheckMemory(void *mem, TSize size)
static constexpr size_t GetAllocationSize(short allocInfo)
void deletePool()
Frees all recycled pool objects.
static constexpr short hookIndex()
static constexpr int AllocationInformationBitCount()
int DbgCountedOpenAllocations(size_t size)
void * allocate(size_t &size, size_t pAlignment)
lang::AllocatorMember< TAllocator > allocMember
A shortcut to a base type.
constexpr bool allowsMemSplit() noexcept
static constexpr short hookIndex(size_t requestedObjectSize)
static constexpr short GetAllocInformation(TIntegral size)
ALIB_DLL TPoolAllocator(TAllocator &pAllocator)
void * reallocate(void *mem, size_t oldSize, size_t &newSize, size_t pAlignment)
void free(void *mem, size_t size)
ALIB_DLL void * AllocateByAllocationInfo(int allocInfo)
lang::AllocatorInterface< TPoolAllocator > operator()()
static constexpr short minimumHookIndex()
ALIB_DLL integer GetPoolSize(size_t size)
ALIB_DLL ~TPoolAllocator()
Destructs this type.
static constexpr short GetAllocInformation()
#define bitsof(type)
Definition alib.inl:1435
#define ALIB_DLL
Definition alib.inl:503
#define ALIB_DCS
Definition alib.inl:1392
#define ALIB_EXPORT
Definition alib.inl:497
#define ALIB_DBG(...)
Definition alib.inl:853
#define ALIB_ASSERT_ERROR(cond, domain,...)
Definition alib.inl:1066
#define ALIB_REL_DBG(releaseCode,...)
Definition alib.inl:855
constexpr int MSB(TIntegral value)
Definition bits.inl:314
constexpr TIntegral LowerMask()
Definition bits.inl:51
constexpr int BitCount(TIntegral value)
Definition bits.inl:215
lang::StdAllocator< T, PoolAllocator > StdPA
lang::integer integer
Type alias in namespace alib.
Definition integers.inl:149
monomem::TPoolAllocator< MonoAllocator > PoolAllocator
monomem::TPoolAllocator< lang::HeapAllocator > PoolAllocatorHA
lang::uinteger uinteger
Type alias in namespace alib.
Definition integers.inl:152
AllocatorInterface< TAllocator > AI() const noexcept
MonoAllocator & GetAllocator() const noexcept
static constexpr void clearMem(T *mem, size_t size, unsigned char magic)
static constexpr void annotate(T *mem, size_t size, unsigned char magic)
static void checkMem(void *mem, const TSize size, unsigned char magic, const char *name)