ALib C++ Library
Library Version: 2510 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
monoallocator.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//==================================================================================================
8#if ALIB_DEBUG_ALLOCATIONS && !ALIB_STRINGS
9# error "Module ALib Strings needed in the ALib Build if Monomem is included and ALIB_DEBUG_ALLOCATIONS is set."
10#endif
11
12ALIB_EXPORT namespace alib { namespace monomem {
13
14// forward declaration
15template<typename TAllocator> class TMonoAllocator;
16
17/// Details of namespace #alib::monomem
18namespace detail {
19
20//==================================================================================================
21/// Internal type defining a memory buffer.
22/// The allocation space is found behind this object itself as it is placed at the start
23/// of each allocated buffer.
24//==================================================================================================
25struct Buffer
26{
27 /// A magic byte, used with the compiler-symbol \ref ALIB_DEBUG_ALLOCATIONS to mark
28 /// memory and detect out-of-bounds writes.
29 /// @see Method \alib{lang;Allocator::dbgCheckMemory}.
30 static constexpr unsigned char MAGIC= 0xA1;
31
32 /// A magic byte written when memory is freed.
33 /// @see Field #CLEAR.
34 static constexpr unsigned char CLEAR= 0xF1;
35
36 char* act; ///< Pointer to the next free space in the buffer.
37 char* end; ///< Pointer to the first byte behind the buffer.
38 Buffer* previous; ///< the previously allocated buffer.
39
40 /// Returns the first offset of an object with given \p{alignment} behind an object with.
41 /// smaller alignment.
42 /// @param firstObject The allocation size of the first object allocated in a buffer.
43 /// @param alignment The allocation alignment of the first object allocated in a buffer.
44 /// @return The value to add to the allocation size to ensure that an object with a certain
45 /// alignment fits after placing \p{firstObject} at the start..
46 static constexpr size_t firstOffset(size_t firstObject, size_t alignment)
47 {
48 return ((firstObject + alignment - 1) / alignment) * alignment;
49 }
50
51 /// Initializes the members of this buffer to reflect the given \p{size}.
52 /// @param size The size of the given \p{mem}.
53 Buffer( size_t size )
54 {
55 act = reinterpret_cast<char*>( this + 1 );
56 end = reinterpret_cast<char*>( this ) + size;
57 }
58
59 //==============================================================================================
60 /// Defaulted default constructor
61 //==============================================================================================
62 Buffer() = default;
63
64 /// @return The size of this buffer.
65 size_t Size() { return size_t(end - reinterpret_cast<char*>(this)) ; }
66
67 //==============================================================================================
68 /// "Frees" all allocated memory, by simply resetting the fill marker of the
69 /// this buffer to the first usable byte of the allocated buffer.
70 //==============================================================================================
71 void reset()
72 {
73 act= reinterpret_cast<char*>( this + 1 );
74 #if ALIB_DEBUG_ALLOCATIONS
75 memset( act, 0xD2, size_t(end - act));
76 #endif
77 }
78
79 //==============================================================================================
80 /// Returns a pointer to an aligned piece of memory of the requested size inside this
81 /// buffer. If there is not enough space left, \c nullptr is returned.
82 ///
83 /// @param size The size to allocate.
84 /// @param alignment The necessary alignment.
85 /// @return \c nullptr on failure, otherwise pointer to the requested memory.
86 //==============================================================================================
87 char* allocate( size_t size, size_t alignment )
88 {
89 ALIB_ASSERT_ERROR( lang::BitCount(alignment) == 1, "MONOMEM",
90 "Requested alignment is not a power of 2:", alignment )
91
92 size_t dbgSize= lang::DbgAlloc::extSize(size);
93
94 // Calc aligned start. Fits to this buffer? If not, just return nullptr
95 char* aligned = reinterpret_cast<char*>( (size_t(act) + alignment - 1) & ~(alignment -1) );
96 if( size_t(end - aligned) < dbgSize )
97 return nullptr;
98 act= aligned + dbgSize;
99
100 lang::DbgAlloc::annotate(aligned, size, MAGIC);
101 return aligned;
102 }
103
104}; // struct Buffer
105
106
107} // namespace alib::momomem[::detail]
108
109//==================================================================================================
110/// Stores the actual state of outer class \b %MonoAllocator.
111/// Retrieved method \alib{monomem;MonoAllocator::TakeSnapshot} and
112/// \alib{monomem;MonoAllocator::Reset(Snapshot)}.
113//==================================================================================================
115{
116 protected:
117 #if !DOXYGEN
118 template<typename TAllocator> friend class TMonoAllocator;
119 #endif
120
121 detail::Buffer* buffer; ///< The current buffer.
122 char* actFill; ///< Pointer to the first free byte in the current buffer.
123
124 /// Internal constructor.
125 /// @param pBuffer The current buffer.
126 /// @param pFill The current fill of \p{buffer}.
127 constexpr Snapshot( detail:: Buffer* pBuffer, char* pFill) noexcept
128 : buffer (pBuffer)
129 , actFill(pFill ) {}
130
131 public:
132 /// Default constructor.
133 /// \note
134 /// Default-constructed snapshots passed to method \alib{monomem;MonoAllocator::Reset(Snapshot)}
135 /// do reset the monotonic allocator to its initial state after construction. All monotonic
136 /// allocated memory is considered 'freed' then.
137 constexpr Snapshot() noexcept
138 : buffer (nullptr)
139 , actFill(nullptr) {}
140
141 /// Returns \c false if this snapshot was never initialized properly (default
142 /// constructed and not copied over).
143 /// @return \c true if this is not a valid snapshot, \c false otherwise.
144 constexpr bool IsValid() noexcept
145 { return buffer != nullptr; }
146
147}; // class Snapshot
148
149/// Statistics for type \alib{monomem;TMonoAllocator}, receivable with method
150/// \alib{monomem::TMonoAllocator;GetStatistics}.
151/// @see Struct \alib{monomem;DbgStatistics} and corresponding method
152/// \alib{monomem::TMonoAllocator;DbgGetStatistics}.
154{
155 /// The number of created buffers.
156 unsigned int QtyBuffers = 0;
157
158 /// The number of created buffers.
159 unsigned int QtyRecyclables = 0;
160
161 /// The number of bytes allocated at the heap.
163
164 /// The number of bytes allocated at the heap from buffers currently used.
165 /// Note: To get the total size, add #HeapSizeRecycled.
166 size_t HeapSize = 0;
167
168 /// The overall number of bytes requested. Note that this value includes the
169 /// losses due to alignment. To get the exact value, method
170 /// \alib{monomem::TMonoAllocator;DbgGetStatistics} needs to be used and its
171 /// information about the alignment waste has to be subtracted.
172 size_t AllocSize = 0;
173
174 /// The number of bytes remaining in buffers, because a next object did not fit. This
175 /// does not include the remaining bytes in the current buffer.
176 size_t BufferWaste = 0;
177
178 /// The free space in the current buffer.
180
181 /// The size of the current buffer.
183
184 /// The planned size of the next buffer (that is not an oversize-allocation).
185 size_t NextBufferSize = 0;
186
187}; // struct Statistics
188
189#if ALIB_DEBUG_MEMORY
190 /// Debug statistics for type \alib{monomem;TMonoAllocator}, receivable with method
191 /// \alib{monomem::TMonoAllocator;DbgGetStatistics}.
192 /// Availability depends on code selector symbol \ref ALIB_DEBUG_MEMORY.
194 {
195 /// The number of allocations performed.
196 size_t QtyAllocations = 0;
197
198 /// The number of allocations performed, cumulated over resets.
200
201 /// The number of allocations that did not create a new buffer .
203
204 /// The number of allocations that did not create a new buffer, cumulated over resets.
206
207 /// The number of allocated space, cumulated over resets.
209
210 /// The number of bytes lost for alignment.
211 size_t AlignmentWaste = 0;
212
213 /// The number of allocations that have been larger than the buffer size.
215
216 /// The number of resets performed.
217 size_t QtyResets = 0;
218 }; // struct DbgStatistics
219#endif
220
221
222// =================================================================================================
223/// \par Important Note
224/// Please consult the \ref alib_contmono_intro "Programmer's Manual" of \alib module
225/// \alib_monomem_nl for an introduction into the rather complex topic of monotonous allocation
226/// and how to use this class.
227///
228/// \par General Behavior
229/// Implements a monotonic allocator. Allocates a series of bigger memory buffers and offers
230/// sequential allocation of portions of those.<br>
231/// With construction, an initial memory buffer is received from the
232/// \ref alib_contmono_chaining "chained allocator".
233/// The size of this buffer is defined with the constructor parameter \p{initialBufferSizeInKB}.
234/// With each necessary allocation of a next buffer, this value can be increased, according
235/// to the optional parameter \p{bufferGrowthInPercent}, which defaults to \c 200, resulting in
236/// doubling the size of each next buffer.
237///
238/// If an invocation of one of the allocation methods requests memory bigger than the
239/// remaining space in the actual (last) buffer, then a new buffer is created and made the actual
240/// buffer. The remaining space of the former actual buffer will not be used for future allocations
241/// and is wasted in this respect.
242///
243/// \par Oversized Allocations
244/// If a requested allocation size exceeds what would be the size of the next buffer, then a new
245/// buffer of the extended size is created. The next allocation will then create a new buffer
246/// which continues the originally defined buffer growth path. In other words:
247/// - Oversized allocations are allowed, and
248/// - the next buffer's size after an oversized allocation will use the size of the
249/// last non-oversized buffer as the base value for calculating the next size.
250///
251/// \note While accepted, oversized allocations should still be avoided, because the current
252/// buffer will not be used for further allocations.
253/// This is a design decision, allowing a more efficient implementation of this class.
254/// Former implementations kept the current buffer as the actual buffer, when an oversized
255/// allocation occured, but this feature was dropped.
256///
257/// \par Resetting
258/// The allocator can be reset to a certain state (see #TakeSnapshot and #Reset), which disposes
259/// all memory behind the snapshot.
260/// Disposed complete buffers will not be freed, but "recycled" with future allocations.<br>
261/// If \ref alib_contmono_class_monoalloc_snapshot "nested snapshots" are used in the right
262/// places, further gains in execution performance can be achieved.
263///
264/// \par External Allocation of the First Buffer
265/// Special constructors of this type allow to pass an existing first buffer for usage.
266/// This allows two fundamental concepts:
267/// - The first buffer might be stack-memory, which can lead to further (sometimes dramatical)
268/// performance improvements.<br>
269/// This feature is leveraged by type \alib{monomem;TLocalAllocator}.
270/// - The first buffer might contain not only already emplaced objects, but even the
271/// \b %TMonoAllocator itself. We name this a <em>"self-contained monotonic allocator"</em>.<br>
272/// This feature is leveraged by type \alib{monomem;TSharedMonoVal}.
273///
274/// \par Debug Features
275/// Depending on the compiler-symbol \ref ALIB_DEBUG_MEMORY, some metrics on instances of this
276/// class become available.
277/// Those might for example be helpful to find a reasonable value for constructor parameters
278/// \p{initialBufferSize} and \p{bufferGrowthInPercent}.
279///
280/// \par See also
281/// - The \ref alib_contmono_intro "Programmer's Manual" of module \alib_monomem_nl.
282/// - The "standard" type definition of this template type \alib{MonoAllocator}, which uses
283/// an \alib{lang;HeapAllocator} as the \ref alib_contmono_chaining "chained allocator".
284///
285/// @tparam TAllocator The underlying allocator to use.<br>
286/// With type definition \alib{MonoAllocator}, this is bound to type
287/// \alib{lang;HeapAllocator}.<br>
288/// For general information see chapter \ref alib_contmono_chaining
289/// of the Programmer's Manual.
290// =================================================================================================
291template<typename TAllocator>
292class TMonoAllocator : public lang::AllocatorMember<TAllocator>
293{
294 protected:
295 /// The allocator type that \p{TAllocator} specifies.
297
298 /// The actual buffer. Contains a link to previously allocated buffers.
300
301 /// The list of buffers that are to be recycled.
303
304 /// The initial allocation size given in the constructor, multiplied with #bufferGrowthInPercent
305 /// with each new buffer created. Allocated buffers may be bigger in the case that a single
306 /// allocation is larger than this value.
308
309 /// Growth factor of subsequently allocated buffers.
310 /// Given by a construction parameter, which in most cases defaults to \c 200,
311 /// doubling the buffer size with each next buffer allocation.
313
314 #if ALIB_DEBUG
315 public:
316 /// A name for this object.
317 /// With debug-compilations, this name has to be given with construction.
318 const char* DbgName;
319
320 protected:
321 /// This flag to mark this allocator to not accept allocations.
322 /// @see Method #DbgLock and chapter \ref alib_contmono_further_debug of the
323 /// Programmer's Manual of this \alibmod_nl.
324 bool dbgLock = false;
325 #endif
326
327 #if ALIB_DEBUG_MEMORY
328 /// Debug statistics measured on the whole run-time of this object.<br>
329 /// Availability depends on code selector symbol \ref ALIB_DEBUG_MEMORY.
331 #endif
332
333 public:
334 #if ALIB_DEBUG_CRITICAL_SECTIONS
335 /// Due to the possibility of beeing self-contained, this type needs special treatment
336 /// in respect to instance \alib{lang;DbgCriticalSections}. It must be neither derived
337 /// nor being a member. Instead, destruction has to be controlled.
338 /// Furthermore, the \ref GrpALibMacros_mod_threads "ALib Module Threads Macros"
339 /// cannot be used.
341 #endif
342
343 protected:
344
345 //==============================================================================================
346 /// This internal allocation method is called by the allocation interface methods, in case
347 /// the current request cannot be trivially satisfied.
348 ///
349 /// Implements the overall strategy of this class in respect to oversized blocks,
350 /// recycling of blocks, etc.
351 ///
352 /// @param size The size of the first object to allocate in the buffer.
353 /// @param alignment The allocation alignment of the first object to allocate.
354 /// @return A pointer to the memory allocated for the object.
355 //==============================================================================================
356 ALIB_DLL char* nextBuffer(size_t size, size_t alignment);
357
358public:
359 /// The type of the allocator that this allocator uses underneath to allocate the buffers,
360 /// given with template parameter \p{TAllocator}.<br>
361 /// The instance can be accessed with inherited methods
362 /// \alib{lang::AllocatorMember;GetAllocator} and \alib{lang::AllocatorMember;AI}.
363 using ChainedAllocator = TAllocator;
364
365 /// Evaluates to \b 1.
366 /// @see Field \alib{lang;Allocator::MIN_ALIGNMENT}.
367 static constexpr size_t MIN_ALIGNMENT = 1;
368
369 /// Evaluates to <c>std::numeric_limits<size_t>::max()</c>.
370 /// @see Field \alib{lang;Allocator::MAX_ALIGNMENT}.
371 static constexpr size_t MAX_ALIGNMENT = (std::numeric_limits<size_t>::max)();
372
373 // ###############################################################################################
374 // ##### Constructors/Destructor
375 // ###############################################################################################
376 public:
377 #if DOXYGEN
378 /// Special constructor that is not initializing this type.
379 /// This can be used if a value of this type is required, but only later it becomes known
380 /// what the initial buffer size and growth factor is to be.
381 ///
382 /// Method #IsInitialized can be used to determine if an allocator was initialized on
383 /// construction.
384 /// If not, a placement-new calling a decent constructor is to be performed before
385 /// construction.
386 ///
387 /// @see Chapter \ref alib_contmono_globalinstance_initialsize of the Programmer's Manual
388 /// of module \alib_monomem.
389 ///
390 /// @param dbgName Has to be specified with debug-compilations only.
391 /// Use macro \ref ALIB_DBG to pass a constant.
392 /// @tparam TRequires Defaulted template parameter. Must not be specified.
393 template<typename TRequires= lang::AllocatorMember<TAllocator>>
394 requires std::default_initializable<TRequires>
395 TMonoAllocator(const char* dbgName, std::nullptr_t) noexcept;
396 #else
397 template<typename TRequires= lang::AllocatorMember<TAllocator>>
398 requires std::default_initializable<TRequires>
399 TMonoAllocator(ALIB_DBG(const char* dbgName,) std::nullptr_t) noexcept
400 : allocMember(TAllocator())
401 , buffer (nullptr)
402 , recyclables(nullptr)
403ALIB_DBG(,DbgName(dbgName)) {}
404 #endif
405
406 #if DOXYGEN
407 /// Constructor that accepts an external first buffer. If this constructor is used, and the
408 /// given \p{initialBuffer} must not be freed to the heap, method
409 /// #destructWithExternalBuffer has to be called right before the allocator is destructed.
410 ///
411 /// \note
412 /// This constructor, together with method #destructWithExternalBuffer enables the efficient
413 /// implementation of derived class \alib{monomem;TLocalAllocator}, as well as
414 /// class \alib{monomem;TSharedMonoVal}.
415 ///
416 /// @param dbgName Has to be specified with debug-compilations only.
417 /// Use macro \ref ALIB_DBG to pass a constant.
418 /// @param pInitialBuffer The initial buffer to use. Has to be aligned with at least
419 /// <c>alignof(void*)</c>.
420 /// @param pInitialBufferSizeInKB The size in kB (1024 bytes) of the given \p{initialBuffer}.
421 /// @param pBufferGrowthInPercent Optional growth factor in percent, applied to each allocation
422 /// of a next buffer size in respect to its previous size.
423 /// Defaults to \c 200, which doubles buffer size with each
424 /// next internal buffer allocation.
425 /// @tparam TRequires Defaulted template parameter. Must not be specified.
426 template<typename TRequires= lang::AllocatorMember<TAllocator>>
427 requires std::default_initializable<TRequires>
428 TMonoAllocator( const char* dbgName,
429 detail::Buffer* pInitialBuffer,
430 size_t pInitialBufferSizeInKB,
431 unsigned int pBufferGrowthInPercent= 200 );
432 #else
433 template<typename TRequires= lang::AllocatorMember<TAllocator>>
434 requires std::default_initializable<TRequires>
435 TMonoAllocator( ALIB_DBG(const char* dbgName,)
436 detail::Buffer* pInitialBuffer,
437 size_t pInitialBufferSizeInKB,
438 unsigned int pBufferGrowthInPercent= 200 )
439 : buffer ( pInitialBuffer )
440 , recyclables ( nullptr )
441 , nextBuffersUsableSize( (pInitialBufferSizeInKB * 1024 * pBufferGrowthInPercent) / 100 )
442 , bufferGrowthInPercent( pBufferGrowthInPercent )
443ALIB_DBG(,DbgName (dbgName))
444 {
445 // assert alignment
446 ALIB_ASSERT_ERROR( (size_t(pInitialBuffer) & (alignof(void*)-1) )== 0, "MONOMEM",
447 "The given initial buffer is not aligned to at least 'alignof(void*)'." )
448
449 #if ALIB_DEBUG_CRITICAL_SECTIONS
450 DbgCriticalSectionsPH.Construct("MonoAllocator");
451 #endif
452 buffer->previous= nullptr;
453 }
454 #endif
455
456
457 #if DOXYGEN
458 /// Alternative constructor version that in addition expects an allocator.
459 ///
460 /// @param dbgName Has to be specified with debug-compilations only.
461 /// Use macro \ref ALIB_DBG to pass a constant.
462 /// @param pAllocator The allocator to use for allocation of buffers.
463 /// @param pInitialBuffer The initial buffer to use. Has to be aligned with at least
464 /// <c>alignof(void*)</c>.
465 /// @param pInitialBufferSizeInKB The size in kB (1024 bytes) of the given \p{initialBuffer}.
466 /// @param pBufferGrowthInPercent Optional growth factor in percent, applied to each allocation
467 /// of a next buffer size in respect to its previous size.
468 /// Defaults to \c 200, which doubles buffer size with each
469 /// next internal buffer allocation.
470 TMonoAllocator( const char* dbgName,
471 TAllocator& pAllocator,
472 detail::Buffer* pInitialBuffer,
473 size_t pInitialBufferSizeInKB,
474 unsigned int pBufferGrowthInPercent= 200 );
475 #else
476 TMonoAllocator( ALIB_DBG(const char* dbgName,)
477 TAllocator& pAllocator,
478 detail::Buffer* pInitialBuffer,
479 size_t pInitialBufferSizeInKB,
480 unsigned int pBufferGrowthInPercent= 200 )
481 : allocMember ( pAllocator )
482 , buffer ( pInitialBuffer )
483 , recyclables ( nullptr )
484 , nextBuffersUsableSize( (pInitialBufferSizeInKB * 1024 * pBufferGrowthInPercent) / 100 )
485 , bufferGrowthInPercent( pBufferGrowthInPercent )
486 ALIB_DBG(,DbgName (dbgName))
487 {
488 // assert alignment
489 ALIB_ASSERT_ERROR( (size_t(pInitialBuffer) & (alignof(void*)-1) )== 0, "MONOMEM",
490 "The given initial buffer is not aligned to at least 'alignof(void*)'." )
491
492 #if ALIB_DEBUG_CRITICAL_SECTIONS
493 DbgCriticalSectionsPH.Construct("MonoAllocator");
494 #endif
495 buffer->previous= nullptr;
496 }
497 #endif
498
499 public:
500 #if DOXYGEN
501 //==============================================================================================
502 /// Constructor.
503 /// A first memory buffer is allocated from #ChainedAllocator.
504 ///
505 /// Parameter \p{bufferGrowthInPercent} determines the growth of memory buffers. The size of a
506 /// next buffer is calculated as:
507 /// newSize= (previousSize * bufferGrowthInPercent) / 100
508 ///
509 /// @param dbgName Has to be specified with debug-compilations only.
510 /// Use macro \ref ALIB_DBG to pass a constant.
511 /// @param pInitialBufferSizeInKB The size in kB (1024 bytes) of the first memory buffer used
512 /// for the allocator itself as well as for the first allocations.
513 /// @param pBufferGrowthInPercent Optional growth factor in percent, applied to each allocation
514 /// of a next buffer size in respect to its previous size.
515 /// Defaults to \c 200, which doubles the buffer size with each
516 /// next internal buffer allocation.
517 /// @tparam TRequires Defaulted template parameter. Must not be specified.
518 //==============================================================================================
519 template<typename TRequires= lang::AllocatorMember<TAllocator>>
520 requires std::default_initializable<TRequires>
521 TMonoAllocator( const char* dbgName,
522 size_t pInitialBufferSizeInKB,
523 unsigned int pBufferGrowthInPercent= 200 );
524 #else
525 template<typename TRequires= lang::AllocatorMember<TAllocator>>
526 requires std::default_initializable<TRequires>
527 TMonoAllocator( ALIB_DBG(const char* dbgName,)
528 size_t pInitialBufferSizeInKB,
529 unsigned int pBufferGrowthInPercent= 200 )
530 : recyclables ( nullptr )
531 , nextBuffersUsableSize( (pInitialBufferSizeInKB * 1024 * pBufferGrowthInPercent) / 100 )
532 , bufferGrowthInPercent( pBufferGrowthInPercent )
533ALIB_DBG(,DbgName(dbgName))
534 {
535 #if ALIB_DEBUG && !ALIB_DEBUG_ASSERTION_PRINTABLES
536 ALIB_ASSERT_ERROR( pInitialBufferSizeInKB, "MONOMEM", "Initial buffer of 0kb requested." )
537 #endif
538 size_t initialBufferSize= pInitialBufferSizeInKB * 1024;
539 buffer= new (TAllocator().allocate(initialBufferSize, alignof(detail::Buffer)))
540 detail::Buffer( initialBufferSize );
541 #if ALIB_DEBUG_CRITICAL_SECTIONS
542 DbgCriticalSectionsPH.Construct("MonoAllocator");
543 #endif
544 buffer->previous= nullptr;
545 }
546 #endif
547
548 #if DOXYGEN
549 //==============================================================================================
550 /// Alternative constructor accepting an allocator instance.
551 /// To be used if template parameter \p{TAllocator} does not equal \alib{lang;HeapAllocator}
552 /// or any (custom) default-constructible allocator type.
553 /// @param dbgName Has to be specified with debug-compilations only.
554 /// Use macro \ref ALIB_DBG to pass a constant.
555 /// @param pAllocator The allocator to use for allocation of buffers.
556 /// @param pInitialBufferSizeInKB The size in kB (1024 bytes) of the first memory buffer used
557 /// for the allocator itself as well as for the first allocations.
558 /// @param pBufferGrowthInPercent Optional growth factor in percent, applied to each allocation
559 /// of a next buffer size in respect to its previous size.
560 /// Defaults to \c 200, which doubles the buffer size with each
561 /// next internal buffer allocation.
562 //==============================================================================================
564 TMonoAllocator( const char* dbgName, TAllocator& pAllocator,
565 size_t pInitialBufferSizeInKB, unsigned int pBufferGrowthInPercent= 200 );
566 #else
568 TMonoAllocator( ALIB_DBG(const char* dbgName,) TAllocator& pAllocator,
569 size_t pInitialBufferSizeInKB, unsigned int pBufferGrowthInPercent= 200 )
570 : allocMember ( pAllocator )
571 , recyclables ( nullptr )
572 , nextBuffersUsableSize( (pInitialBufferSizeInKB * 1024 * pBufferGrowthInPercent) / 100 )
573 , bufferGrowthInPercent( pBufferGrowthInPercent )
574ALIB_DBG(,DbgName(dbgName))
575 {
576 ALIB_ASSERT_ERROR( pInitialBufferSizeInKB, "MONOMEM", "Initial buffer of 0kb requested." )
577 size_t initialBufferSize= pInitialBufferSizeInKB * 1024;
578 buffer= new (TAllocator().allocate(initialBufferSize, alignof(detail::Buffer)))
579 detail::Buffer( initialBufferSize );
580 #if ALIB_DEBUG_CRITICAL_SECTIONS
581 DbgCriticalSectionsPH.Construct("MonoAllocator");
582 #endif
583 buffer->previous= nullptr;
584 }
585 #endif
586
587 /// Not copyable.
589
590 /// Not movable.
592
593 /// Destructor. Disposes all memory allocated with #ChainedAllocator.
596
597
598 //##############################################################################################
599 /// @name Self-Contained Creation
600 //##############################################################################################
601
602 #if DOXYGEN
603 //==============================================================================================
604 /// This static method creates an object of this type inside "itself", aka inside its first
605 /// allocated buffer.
606 /// Instances created with this method have to be deleted by only invoking the destructor,
607 /// e.g., using \alib{lang;Destruct}.
608 ///
609 /// Method #Reset must not be called using its default parameter when an instance of this type
610 /// was created by this method. Instead, if reset operations are desired, a snapshot has to be
611 /// taken (see method #TakeSnapshot) right after the invocation of this method and maybe
612 /// other initial members that should survive a reset, which then has to be passed to method
613 /// \b Reset.<br>
614 /// Alternatively, if only the monotonic allocator should survive the reset, overloaded method
615 /// #Reset(size_t, size_t) might be used, passing <c>sizeof(TMonoAllocator<T>)</c> and
616 /// <c>alignof(TMonoAllocator<T>)</c> as parameters.
617 ///
618 /// @param dbgName Has to be specified with debug-compilations only.
619 /// Use macro \ref ALIB_DBG to pass a constant.
620 /// @param pAllocator The allocator used for creating the first buffer.
621 /// @param initialBufferSizeInKB The size of memory the buffers allocated in kilobytes.
622 /// @param bufferGrowthInPercent Optional growth factor in percent, applied to the buffer size
623 /// with each next buffer allocation.
624 /// Values provided should be greater than 100.<br>
625 /// Defaults to \c 200, which doubles buffer size with each
626 /// next internal buffer allocation.
627 /// @return A pointer to an instance of this type \b MonoAllocator residing in its first
628 /// created buffer.
629 //==============================================================================================
631 static TMonoAllocator* Create( const char* dbgName,
632 TAllocator& pAllocator,
633 size_t initialBufferSizeInKB,
634 unsigned int bufferGrowthInPercent= 200 );
635 #else
637 static TMonoAllocator* Create( ALIB_DBG(const char* dbgName,)
638 TAllocator& pAllocator,
639 size_t initialBufferSizeInKB,
640 unsigned int bufferGrowthInPercent= 200 );
641 #endif
642
643 #if DOXYGEN
644 //==============================================================================================
645 /// Same as #Create(const char*, TAllocator&, size_t, unsigned int), but misses the allocator
646 /// parameter.
647 /// Used with chained allocators that are default-constructible (e.g., \b HeapAllocator):
648 ///
649 /// @param dbgName Has to be specified with debug-compilations only.
650 /// Use macro \ref ALIB_DBG to pass a constant.
651 /// @param initialBufferSizeInKB The size of memory the buffers allocated in kilobytes.
652 /// @param bufferGrowthInPercent Optional growth factor in percent, applied to the buffer size
653 /// with each next buffer allocation.
654 /// Values provided should be greater than 100.<br>
655 /// Defaults to \c 200, which doubles buffer size with each
656 /// next internal buffer allocation.
657 /// @tparam TRequires Defaulted template parameter. Must not be specified.
658 /// @return A pointer to an instance of this type \b MonoAllocator residing in its first
659 /// created buffer.
660 //==============================================================================================
661 template<typename TRequires= lang::AllocatorMember<TAllocator>>
662 requires std::default_initializable<TRequires>
663 static TMonoAllocator* Create( const char* dbgName,
664 size_t initialBufferSizeInKB,
665 unsigned int bufferGrowthInPercent= 200 );
666 #else
667 template<typename TRequires= lang::AllocatorMember<TAllocator>>
668 requires std::default_initializable<TRequires>
669 static TMonoAllocator* Create( ALIB_DBG( const char* dbgName, )
670 size_t initialBufferSizeInKB,
671 unsigned int bufferGrowthInPercent= 200 )
672 {
673 TAllocator a;
674 return Create( ALIB_DBG(dbgName,) a, initialBufferSizeInKB, bufferGrowthInPercent );
675 }
676 #endif
677
678
679 /// This method has to be called before destruction of an instance, in the case that
680 /// instance was allocated using a special version of the constructors that accept an external
681 /// \alib{monomem::detail;Buffer}.
682 /// This will remove the initially given buffer from the list of buffers, and thus this buffer
683 /// not be deleted. Only if the memory was simply heap-allocated using <c>std::malloc</c>,
684 /// <c>C++ new operator</c>, or \alib{lang;HeapAllocator}, and if the memory is intended to be
685 /// freed, this method may not be called. As a sample, class \alib{monomem;TLocalAllocator},
686 /// which uses stack-memory for the first buffer, will call this method in its destructor.
687 ///
688 /// \attention
689 /// 1. If this method is not called when needed, this leads to undefined behavior.
690 /// 2. If this method is called without the provision of an external buffer on construction,
691 /// a memory leak occurs. (The first buffer this allocator allocated, will not be freed.)
692 /// 3. After this method has been invoked, the instance becomes unusable and is to be
693 /// destructed in a next step.
694 ///
695 /// Note that as an exception to the rule, this method's name starts with a lowercase
696 /// letter as if it was protected, while it has to be public.
699
700
701 /// Tests if non-initializing constructor #TMonoAllocator(const char*, std::nullptr_t) was used.
702 /// @return \c false if this allocator needs to be initialized by performing a placement-new on
703 /// <c>this</c>.
704 bool IsInitialized() const noexcept { return buffer != nullptr; }
705
706
707
708 // #############################################################################################
709 /// @name lang::Allocator Implementation
710 // #############################################################################################
711
712 /// Allocate memory from the internal buffer. If the buffer's size is exceeded, a next buffer
713 /// is allocated and used.
714 /// @param size The size of memory the block to allocate in bytes.
715 /// With this allocator this is not an input/output parameter.
716 /// @param alignment The (minimum) alignment of the memory block to allocate in bytes.
717 /// See Chapter \ref alib_contmono_further_alignment of the Programmer's
718 /// Manual of this module.
719 /// @return Pointer to the allocated memory.
720 inline void* allocate( size_t size, size_t alignment )
721 {
722 #if ALIB_DEBUG_CRITICAL_SECTIONS
723 DbgCriticalSectionsPH.Get()->Acquire(ALIB_CALLER);
724 #endif
726
727 ALIB_ASSERT_ERROR( buffer , "MONOMEM",
728 "This MonoAllocator was constructed passing 'nullptr' and is not usable.")
729 ALIB_ASSERT_ERROR( !dbgLock, "MONOMEM", "This MonoAllocator is locked.")
730 ALIB_ASSERT_ERROR(lang::BitCount(alignment) == 1, "MONOMEM",
731 "The requested alignment has to be a power of 2. Requested is: ", int(alignment) )
732
733 #if ALIB_DEBUG_MEMORY
734 ++dbgStats.QtyAllocations;
735 DBG_ALIGNMENT_INIT( buffer )
736 #endif
737
738 #if ALIB_DEBUG_MEMORY
739 if( lang::DbgAlloc::extSize( size ) > size_t(buffer->end - reinterpret_cast<char*>(buffer)) / 2 )
740 ALIB_WARNING( "MONOMEM",
741 "MonoAllocator: Allocation size exceeds 1/2 of the current buffer size.\n"
742 "The allocator's buffer size should be increased.\n"
743 "Requested size: ", size )
744 #endif
745
746
747 char* mem= buffer->allocate(size, alignment);
748 if ( mem )
749 {
750 #if ALIB_DEBUG_MEMORY
751 DBG_ALIGNMENT_MEASURE(buffer)
752 #endif
753 #if ALIB_DEBUG_CRITICAL_SECTIONS
754 DbgCriticalSectionsPH.Get()->Release(ALIB_CALLER);
755 #endif
756 return mem;
757 }
758
759 mem= nextBuffer( size, alignment );
760 #if ALIB_DEBUG_CRITICAL_SECTIONS
761 DbgCriticalSectionsPH.Get()->Release(ALIB_CALLER);
762 #endif
763 return mem;
764 }
765
766 /// Grows a piece of memory.
767 /// If a new allocation had to be performed, the existing data is copied.
768 /// Note that this allocator implementation never shrinks memory, thus
769 /// if \p{oldSize} is greater than \p{newSize}, the original memory is returned.<br>
770 /// @param mem The memory to reallocate.
771 /// @param oldSize The current size of \p{mem}.
772 /// @param newSize The now required size of \p{mem} in bytes.
773 /// With this allocator this is not an input/output parameter.
774 /// @param alignment The (minimum) alignment of the memory block to allocate in bytes.
775 /// (Has to be the same as before, but this is not tested here).
776 /// See Chapter \ref alib_contmono_further_alignment of the Programmer's
777 /// Manual of this module.
778 /// @return Pointer to the re-allocated memory block.
779 inline void* reallocate( void* mem, size_t oldSize, size_t newSize, size_t alignment )
780 {
781 ALIB_ASSERT_ERROR( !dbgLock, "MONOMEM", "This MonoAllocator is locked.")
783 ALIB_ASSERT_ERROR(lang::BitCount(alignment) == 1, "MONOMEM",
784 "The requested alignment has to be a power of 2. Requested is: ", alignment )
785
787 if( oldSize >= newSize )
788 return mem;
789
790 if( buffer->act - lang::DbgAlloc::extSize(oldSize) == mem )
791 buffer->act-= lang::DbgAlloc::extSize(oldSize);
792
793 auto* newMem= allocate( newSize, alignment );
794 if( newMem != mem )
795 std::memcpy( newMem, mem, oldSize );
796
797 #if ALIB_DEBUG_MEMORY
798 else
799 --dbgStats.QtyAllocations;
800 #endif
802 return newMem;
803 }
804
805 /// This method is empty for this allocator and optimized out. Only if the compiler-symbol
806 /// \ref ALIB_DEBUG_ALLOCATIONS is set, the method will overwrite the freed memory with
807 /// character <c>0xD2</c>. This is why method #allowsMemSplit returns \c false if that
808 /// symbol is set and some few optimizations will not be performed in that mode, for example,
809 /// the reuse of bucket arrays as recycled node objects when resizing hashtables.
810 ///
811 /// @param mem The memory to free.
812 /// @param size The allocated size.
813 inline void free( void* mem, size_t size) const
814 {
815 ALIB_ASSERT_ERROR( !dbgLock, "MONOMEM", "This MonoAllocator is locked.")
818 }
819
820 /// This is an empty implementation of the prototyped method.
821 /// It is empty because this allocator never returns a higher allocation size than requested.
822 /// \alib{lang;Allocator::dbgAcknowledgeIncreasedAllocSize}.
823 /// @tparam TSize The type of parameter \p{allocSize}. (Deduced by the compiler.)
824 template<typename TSize>
825 void dbgAcknowledgeIncreasedAllocSize( void*, TSize ) const {}
826
827 /// Returns a temporary object (which is usually optimized out together with a call to this
828 /// operator) providing high-level convenience methods for allocation.
829 /// @see Class \alib{lang::AllocatorInterface}
830 /// @return A temporary high-level interface into the allocator.
833
834 #if DOXYGEN
835 /// See the description of this method with prototype \alib{lang;Allocator::allowsMemSplit}.<br>
836 /// (Note: This method is static. For technical reasons this cannot be reflected in this
837 /// documentation)
838 /// @return \c true, except if the compiler-symbol \ref ALIB_DEBUG_ALLOCATIONS is given.
839 constexpr bool allowsMemSplit() noexcept;
840 #else
841 static inline constexpr bool allowsMemSplit() noexcept
842 {
843 #if !ALIB_DEBUG_ALLOCATIONS
844 return true;
845 #else
846 return false;
847 #endif
848 }
849 #endif
850
851 //##############################################################################################
852 /// @name Snapshots and Reset
853 //##############################################################################################
854
855 //==============================================================================================
856 /// Saves the current state of the allocator and returns this information as a \b Snapshot
857 /// value. Such snapshots may be passed to method #Reset(Snapshot).
858 ///
859 /// Note that the actual memory is \b not copied and restored. In this respect the word
860 /// "Snapshot" is overstating. What is stored are the current use of memory, but not it's
861 /// contents.
862 ///
863 /// @return A (lightweight) snapshot value object.
864 //==============================================================================================
866 {
867 return Snapshot(buffer, buffer->act);
868 }
869
870 //==============================================================================================
871 /// Resets this allocator to the given \alib{monomem;Snapshot}.
872 /// Parameter \p{snapshot} is defaulted with a default-constructed \b Snapshot, which
873 /// completely resets the allocator.
874 ///
875 /// With a reset, the memory buffers which had been allocated after taking the given
876 /// \p{snapshot}, are not released back to the operating system, but re-used with future
877 /// monotonic allocations.
878 ///
879 /// This method is useful in cases where some permanent objects which are allocated first
880 /// have to be preserved with resets.
881 ///
882 /// Note that snapshots taken after the given one become invalid. This is because
883 /// class \b Snapshot is only a simple lightweight class that marks the currently
884 /// used buffer and its fill level.
885 ///
886 /// @param snapshot The snapshot to reset to.
887 //==============================================================================================
889 void Reset( Snapshot snapshot= Snapshot() );
890
891 //==============================================================================================
892 /// Special version of #Reset(Snapshot) which resets this allocator to the first buffer
893 /// and within that, behind the first object of the given size.<br>
894 /// This method is used by class \alib{monomem;TSharedMonoVal} to avoid the need of storing
895 /// a snapshot behind itself.
896 ///
897 /// If the compiler-symbol \ref ALIB_DEBUG_ALLOCATIONS is set, then all freed memory is
898 /// overwritten with <c>0xD2</c>. This helps to identify invalid reset operations.
899 /// @param firstObjectSize The size of the first emplaced object.
900 /// @param firstObjectAlignment The alignment of the first emplaced object.
901 //==============================================================================================
902 void Reset( size_t firstObjectSize, size_t firstObjectAlignment )
903 {
904 Reset( ALIB_DBG( Snapshot(nullptr, reinterpret_cast<char*>(1)) ) );
905 buffer->allocate( firstObjectSize, firstObjectAlignment );
906 }
907
908 //##############################################################################################
909 /// @name Statistics and Debug-Interface
910 //##############################################################################################
911
912 /// Fills the given \p{result} record with statistical information about this allocator.
913 /// @see Method #DbgGetStatistics, which delivers further information but is only available
914 /// with compilation symbol \ref ALIB_DEBUG_MEMORY set.
915 /// @param result The object to write the result into. (Will be reset before use.)
917 void GetStatistics( Statistics& result );
918
919 /// Lock or unlock this allocator.
920 /// If locked, an ALib assertion is raised if allocations are performed.
921 /// This can be quite useful to detect allocations with an allocator that is shared
922 /// between different code entities and to enforce certain allocation contracts.
923 ///
924 /// With release-compilations, this method is empty and optimized out.
925 /// @see Chapter \ref alib_contmono_further_debug of the Programmer's Manual of this
926 /// \alibmod_nl.
927 /// @param onOff The state to set.
928 void DbgLock(bool onOff) noexcept { ALIB_DBG( dbgLock= onOff;) (void) onOff; }
929
930 /// Allows access to the internal buffer.
931 /// For example, this is used with function \alib{monomem;DbgDumpStatistics}.
932 /// With release-compilations, this method is empty and not useable.
933 /// @return A pointer to the internal buffer.
934 detail::Buffer* DbgGetBuffer() noexcept { ALIB_REL_DBG( return nullptr;, return buffer;) }
935
936 /// Allows access to the internal buffer (const overload).
937 /// For example, this is used with function \alib{monomem;DbgDumpStatistics}.
938 /// With release-compilations, this method is empty and not useable.
939 /// @return A pointer to the internal buffer.
940 const detail::Buffer* DbgGetBuffer() const noexcept { ALIB_REL_DBG( return nullptr;, return buffer;) }
941
942 /// If the compiler-symbol \ref ALIB_DEBUG_ALLOCATIONS is not set, this method is empty and will
943 /// be optimized out. Otherwise, this will raise an \alib assertion if the piece of allocated
944 /// memory is corrupted or its allocation size is not rightfully given by the using code.
945 /// @see Chapter \ref alib_contmono_further_debug of the Programmer's Manual.
946 ///
947 /// @tparam TSize The type of parameter \p{size}. (Deduced by the compiler.)
948 /// @param mem The address of the allocated object.
949 /// @param size The requested allocation size of the object.
950 template<typename TSize>
951 void dbgCheckMemory( void* mem, TSize size )
953
954 #if ALIB_DEBUG_MEMORY
955 //==========================================================================================
956 /// Returns allocation statistics for manual performance optimization.
957 /// \par Availability
958 /// This method is included only if the code selector symbol \ref ALIB_DEBUG_MEMORY is set.
959 ///
960 /// @return The internal statistics struct.
961 //==========================================================================================
962 const DbgStatistics& DbgGetStatistics() const { return dbgStats; }
963 #endif
964
965}; // class TMonoAllocator
966
967
968// ############################# Template instantiation declaration ############################
969#if !DOXYGEN
970 extern template ALIB_DLL class TMonoAllocator<lang::HeapAllocator>;
971#endif
972
973// ###################################### Global Allocator #####################################
974
975/// This is the global monotonic allocator singleton instance.
976/// It's initial size defaults to \ 128 kilobytes. This can be tweaked by performing a
977/// placement-new on this instance before \ref alib_mod_bs "bootstrapping ALib".
978///
979/// \see
980/// - Chapter \ref alib_contmono_globalinstance of the Programmer's Manual of this \alibmod_nl.
981/// - \b Lock instance \alib{monomem::GLOBAL_ALLOCATOR_LOCK}
982extern ALIB_DLL TMonoAllocator<lang::HeapAllocator> GLOBAL_ALLOCATOR;
983
984#if !ALIB_SINGLE_THREADED
985/// This <em>mutex</em> is used to protect the \alib{monomem;GLOBAL_ALLOCATOR} from racing
986/// conditions in multithreaded software.<br>
987/// If the compiler-symbol \ref ALIB_DEBUG_CRITICAL_SECTIONS is set, this lock will be attached
988/// to the \alib{lang;DbgCriticalSections} instance in #GLOBAL_ALLOCATOR during bootstrap.
989/// Thus, an assertion will be raised if the \alib{monomem;GLOBAL_ALLOCATOR} is used without
990/// locking this mutex.<br>
991/// This is a recursive lock.
992/// This allows using the \alib{lang;AllocatorInterface;high-level allocation interface} with
993/// allocations, which constructs objects.
994/// These objects might recursively use the global allocator for their members.
996#endif
997
998} // namespace alib[::monomem]
999
1000/// Type alias in namespace \b alib.
1001/// This alias fixes template parameter \p{TAllocator} (which defines the
1002/// \ref alib_contmono_chaining "chained allocator") to type \alib{lang;HeapAllocator}.
1004
1005/// Type alias in namespace \b alib to denote the use of a \alib{MonoAllocator}
1006/// with type \alib{lang::StdContainerAllocator}.
1007template<typename T>
1009
1010
1011
1012} // namespace [alib]
1013
1014
constexpr Snapshot(detail::Buffer *pBuffer, char *pFill) noexcept
char * actFill
Pointer to the first free byte in the current buffer.
constexpr Snapshot() noexcept
detail::Buffer * buffer
The current buffer.
constexpr bool IsValid() noexcept
const DbgStatistics & DbgGetStatistics() const
TMonoAllocator(const char *dbgName, std::nullptr_t) noexcept
ALIB_DLL ~TMonoAllocator()
Destructor. Disposes all memory allocated with ChainedAllocator.
TMonoAllocator(const char *dbgName, TAllocator &pAllocator, detail::Buffer *pInitialBuffer, size_t pInitialBufferSizeInKB, unsigned int pBufferGrowthInPercent=200)
void DbgLock(bool onOff) noexcept
TMonoAllocator(const char *dbgName, size_t pInitialBufferSizeInKB, unsigned int pBufferGrowthInPercent=200)
lang::Placeholder< lang::DbgCriticalSections > DbgCriticalSectionsPH
void free(void *mem, size_t size) const
constexpr bool allowsMemSplit() noexcept
lang::AllocatorMember< TAllocator > allocMember
The allocator type that TAllocator specifies.
void dbgCheckMemory(void *mem, TSize size)
detail::Buffer * DbgGetBuffer() noexcept
TMonoAllocator(const TMonoAllocator &)=delete
Not copyable.
TMonoAllocator(const char *dbgName, detail::Buffer *pInitialBuffer, size_t pInitialBufferSizeInKB, unsigned int pBufferGrowthInPercent=200)
void dbgAcknowledgeIncreasedAllocSize(void *, TSize) const
lang::AllocatorInterface< TMonoAllocator > operator()()
void * allocate(size_t size, size_t alignment)
static ALIB_DLL TMonoAllocator * Create(const char *dbgName, TAllocator &pAllocator, size_t initialBufferSizeInKB, unsigned int bufferGrowthInPercent=200)
static TMonoAllocator * Create(const char *dbgName, size_t initialBufferSizeInKB, unsigned int bufferGrowthInPercent=200)
ALIB_DLL TMonoAllocator(const char *dbgName, TAllocator &pAllocator, size_t pInitialBufferSizeInKB, unsigned int pBufferGrowthInPercent=200)
void * reallocate(void *mem, size_t oldSize, size_t newSize, size_t alignment)
ALIB_DLL char * nextBuffer(size_t size, size_t alignment)
TMonoAllocator(TMonoAllocator &&)=delete
Not movable.
bool IsInitialized() const noexcept
ALIB_DLL void GetStatistics(Statistics &result)
void Reset(size_t firstObjectSize, size_t firstObjectAlignment)
ALIB_DLL void Reset(Snapshot snapshot=Snapshot())
const detail::Buffer * DbgGetBuffer() const noexcept
#define ALIB_DLL
Definition alib.inl:496
#define ALIB_CALLER
Definition alib.inl:1001
#define ALIB_WARNING(domain,...)
Definition alib.inl:1046
#define ALIB_EXPORT
Definition alib.inl:488
#define ALIB_DBG(...)
Definition alib.inl:836
#define ALIB_ASSERT_ERROR(cond, domain,...)
Definition alib.inl:1049
#define ALIB_REL_DBG(releaseCode,...)
Definition alib.inl:838
void SingleThreaded()
Definition assert.cpp:141
constexpr int BitCount(TIntegral value)
Definition bits.inl:222
Details of namespace alib::monomem.
ALIB_DLL TMonoAllocator< lang::HeapAllocator > GLOBAL_ALLOCATOR
ALIB_DLL RecursiveLock GLOBAL_ALLOCATOR_LOCK
lang::StdContainerAllocator< T, MonoAllocator > SCAMono
monomem::TMonoAllocator< lang::HeapAllocator > MonoAllocator
threads::RecursiveLock RecursiveLock
Type alias in namespace alib.
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 constexpr size_t extSize(TIntegral size)
static void checkMem(void *mem, const TSize size, unsigned char magic, const char *name)
size_t QtyAllocationsInclResets
The number of allocations performed, cumulated over resets.
size_t QtyTrivialAllocationsInclResets
The number of allocations that did not create a new buffer, cumulated over resets.
size_t AlignmentWaste
The number of bytes lost for alignment.
size_t QtyBufferSizeExceeds
The number of allocations that have been larger than the buffer size.
size_t QtyAllocations
The number of allocations performed.
size_t AllocSizeInclResets
The number of allocated space, cumulated over resets.
size_t QtyTrivialAllocations
The number of allocations that did not create a new buffer .
size_t QtyResets
The number of resets performed.
size_t CurrentBufferSize
The size of the current buffer.
size_t HeapSizeRecycled
The number of bytes allocated at the heap.
size_t NextBufferSize
The planned size of the next buffer (that is not an oversize-allocation).
size_t CurrentBufferFree
The free space in the current buffer.
unsigned int QtyBuffers
The number of created buffers.
unsigned int QtyRecyclables
The number of created buffers.
static constexpr size_t firstOffset(size_t firstObject, size_t alignment)
char * end
Pointer to the first byte behind the buffer.
char * act
Pointer to the next free space in the buffer.
Buffer * previous
the previously allocated buffer.
Buffer()=default
Defaulted default constructor.
static constexpr unsigned char CLEAR
static constexpr unsigned char MAGIC
char * allocate(size_t size, size_t alignment)