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