17# if ALIB_STRINGS && ALIB_DEBUG_MONOMEM
20# if ALIB_THREADS && ALIB_CAMP
24# if ALIB_DEBUG_MONOMEM && ALIB_ALOX
27# if ALIB_CAMP && ALIB_DEBUG
34namespace alib {
namespace monomem {
38template<
typename TAllocator>
40 TAllocator& pAllocator,
41 size_t initialBufferSizeInKB,
42 unsigned int pBufferGrowthInPercent )
44 using TMA= TMonoAllocator<TAllocator>;
45 ALIB_ASSERT_ERROR( initialBufferSizeInKB,
"MONOMEM",
"Initial buffer of 0kb requested." )
47 auto size= initialBufferSizeInKB * 1024;
48 auto* mem= pAllocator.allocate( size, alignof(detail::Buffer) );
49 auto* firstBuffer= new (mem) detail::Buffer( initialBufferSizeInKB * 1024 );
51 auto* result = reinterpret_cast<TMA*>( firstBuffer->allocate( sizeof(TMA), alignof(TMA) ) );
52 return new (result) TMA(
ALIB_DBG(pDbgName,) pAllocator, firstBuffer,
53 initialBufferSizeInKB, pBufferGrowthInPercent );
55#include "alib/lang/callerinfo_methods.hpp"
58template<
typename TAllocator>
61 #if ALIB_DEBUG_CRITICAL_SECTIONS
62 DbgCriticalSectionsPH.Destruct();
65 #if ALIB_DEBUG_MONOMEM
70 auto* cnk= recyclables;
73 #if ALIB_DEBUG_MONOMEM
77 auto* next= cnk->previous;
78 allocMember::GetAllocator().free( cnk, cnk->Size() );
86 auto* next= cnk->previous;
89 allocMember::GetAllocator().free( cnk, cnk->Size() );
91 #if ALIB_DEBUG_MONOMEM
98 #if ALIB_DEBUG_MONOMEM
100 "ALIB_DEBUG_MONOMEM Warning: More than 15 buffers allocated. "
101 "Buffer size might be increased? #Buffers: ",
int(cntBuffers) )
107template<
typename TAllocator>
113 if( snapshot.
buffer ==
nullptr )
121 || snapshot.
actFill ==
reinterpret_cast<char*
>(1),
123 "A full MonoAllocator::Reset() was requested for a self-contained monotonic "
124 "allocator created with MonoAllocator::Create()." )
129 #if ALIB_DEBUG_MONOMEM
131 #if ALIB_DEBUG_CRITICAL_SECTIONS
134 GetStatistics(stats);
135 #if ALIB_DEBUG_CRITICAL_SECTIONS
138 dbgStats.QtyAllocationsInclResets += dbgStats.QtyAllocations;
139 dbgStats.QtyTrivialAllocationsInclResets+= dbgStats.QtyTrivialAllocations;
140 dbgStats.AllocSizeInclResets += (stats.
AllocSize - dbgStats.AlignmentWaste);
141 ++dbgStats.QtyResets;
142 dbgStats.QtyAllocations = 0;
143 dbgStats.QtyTrivialAllocations = 0;
144 dbgStats.AlignmentWaste = 0;
145 dbgStats.QtyBufferSizeExceeds = 0;
150 while( it != snapshot.
buffer )
152 #if !ALIB_DEBUG_ALLOCATIONS
157 if ( it->
previous !=
nullptr || snapshot.
actFill !=
reinterpret_cast<char*
>(1) )
162 buffer->act=
reinterpret_cast<char*
>( buffer + 1 );
168 if ( next ==
nullptr )
170 #if ALIB_DEBUG_ALLOCATIONS
171 if ( snapshot.
actFill !=
reinterpret_cast<char*
>(1) )
172 memset( buffer->act, 0xD2,
size_t(buffer->end - buffer->act) );
189 #if ALIB_DEBUG_ALLOCATIONS
190 memset( buffer->act, 0xD2,
size_t(buffer->end - buffer->act) );
194template<
typename TAllocator>
200 while( (*it)->previous )
212template<
typename TAllocator>
219 auto nextBUS= nextBuffersUsableSize;
227 #if ALIB_DEBUG_MONOMEM
228 ++dbgStats.QtyBufferSizeExceeds;
231 "MonoAllocator: Allocation size exceeds the next buffers' size.\n"
232 "The allocator's buffer size should be increased.\n"
234 static_cast<int>(size ) )
241 { DBG_ALIGNMENT_INIT( recyclable )
242 char* mem= recyclable->
allocate( size, alignment ); DBG_ALIGNMENT_MEASURE( recyclable )
245 *previousPointer= recyclable->
previous;
252 previousPointer= &recyclable->
previous;
258 buffer=
new (allocMember::GetAllocator().allocate(nextBUS,
alignof(
void*)))
detail::Buffer( nextBUS );
259 if ( nextBUS == nextBuffersUsableSize)
260 nextBuffersUsableSize= (nextBuffersUsableSize * bufferGrowthInPercent) / 100;
261 buffer->
previous = previousBuffer; DBG_ALIGNMENT_INIT( buffer )
263 char* mem= buffer->
allocate( size, alignment ); DBG_ALIGNMENT_MEASURE( buffer )
270template<
typename TAllocator>
283 while( it !=
nullptr )
295 while( it !=
nullptr )
304#if ALIB_CAMP && ALIB_DEBUG
305template<
typename TAllocator>
309 GetStatistics(stats);
313 nf.
Flags |= NumberFormatFlags::WriteGroupChars;
315 result <<
"MonoAllocator Usage Statistics:" <<
NNEW_LINE;
319 result <<
" Current buffer used: " <<
NFormat( buffer->act -
reinterpret_cast<char*
>(buffer), &nf ) <<
NNEW_LINE;
330 #if ALIB_DEBUG_MONOMEM
331 result <<
" Dbg: Allocations: " <<
NFormat( dbgStats.QtyAllocations , &nf ) <<
NNEW_LINE;
332 result <<
" Dbg: Non-trivial: " <<
NFormat( dbgStats.QtyAllocations- dbgStats.QtyTrivialAllocations, &nf ) <<
NNEW_LINE;
333 result <<
" Dbg: Resets: " <<
NFormat( dbgStats.QtyResets , &nf ) <<
NNEW_LINE;
335 result <<
" Dbg: #Allocs/buffer: ";
340 result <<
" Dbg: Alignm. waste: " <<
NFormat( dbgStats.AlignmentWaste , &nf )
342 result <<
" Dbg: Qty exceeds: " <<
NFormat( dbgStats.QtyBufferSizeExceeds , &nf ) <<
NNEW_LINE;
char * actFill
Pointer to the first free byte in the current buffer.
detail::Buffer * buffer
The current buffer.
ALIB_API NAString DbgDumpStatistics()
ALIB_API void GetStatistics(Statistics &result)
ALIB_API char * nextBuffer(size_t size, size_t alignment)
ALIB_API ~TMonoAllocator()
Destructor. Disposes all memory allocated with ChainedAllocator.
ALIB_API void Reset(Snapshot snapshot=Snapshot())
ALIB_API void destructWithExternalBuffer()
static ALIB_API TMonoAllocator * Create(const char *dbgName, TAllocator &pAllocator, size_t initialBufferSizeInKB, unsigned int bufferGrowthInPercent=200)
#define ALIB_WARNING(...)
#define ALIB_WARNINGS_RESTORE
#define ALIB_ASSERT_ERROR(cond,...)
#define ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE
#define ALIB_DCS_WITH(CS)
#define ALIB_ASSERT_WARNING(cond,...)
#define ALIB_ASSERT(cond)
strings::TFormat< nchar > NFormat
Type alias in namespace alib.
constexpr NCString NNEW_LINE
A zero-terminated string containing the new-line character sequence.
lang::integer integer
Type alias in namespace alib.
static constexpr size_t extSize(TIntegral size)
unsigned int QtyBuffers
The number of created buffers.
size_t CurrentBufferFree
The free space in the current buffer.
size_t HeapSizeRecycled
The number of bytes allocated at the heap.
size_t CurrentBufferSize
The size of the current buffer.
unsigned int QtyRecyclables
The number of created buffers.
size_t NextBufferSize
The planned size of the next buffer (that is not an oversize-allocation).
static constexpr size_t firstOffset(size_t firstObject, size_t alignment)
char * end
Pointer to the first byte behind the buffer.
ALIB_FORCE_INLINE char * allocate(size_t size, size_t alignment)
char * act
Pointer to the next free space in the buffer.
Buffer * previous
the previously allocated buffer.