8#ifndef HPP_ALIB_MONOMEM_MONOALLOCATOR
9#define HPP_ALIB_MONOMEM_MONOALLOCATOR 1
15#include "alib/lang/allocation.hpp"
20#if ALIB_DEBUG_CRITICAL_SECTIONS
23#if ALIB_DEBUG_ALLOCATIONS
25# error "Module ALib Strings needed in the ALib Distribution if Monomem is included and ALIB_DEBUG_ALLOCATIONS is set."
38# if ALIB_DEBUG_MONOMEM && ALIB_ALOX
39# define DBG_ALIGNMENT_INIT(buffer) size_t qtyLeftBeforeAlloc= size_t(buffer->end - buffer->act);
40# define DBG_ALIGNMENT_MEASURE(buffer) if(mem) dbgStats.AlignmentWaste+= \
41 ( qtyLeftBeforeAlloc \
42 - size_t(buffer->end - buffer->act) \
43 - lang::DbgAlloc::extSize(size) );
45# define DBG_ALIGNMENT_INIT(...)
46# define DBG_ALIGNMENT_MEASURE(...)
50namespace alib {
namespace monomem {
53template<
typename TAllocator>
class TMonoAllocator;
68 static constexpr unsigned char MAGIC= 0xA1;
72 static constexpr unsigned char CLEAR= 0xF1;
84 static constexpr size_t firstOffset(
size_t firstObject,
size_t alignment)
86 return ((firstObject + alignment - 1) / alignment) * alignment;
95 act =
reinterpret_cast<char*
>(
this + 1 );
96 end =
reinterpret_cast<char*
>( this ) + size;
106 size_t Size() {
return size_t(
end -
reinterpret_cast<char*
>(
this)) ; }
115 act=
reinterpret_cast<char*
>(
this + 1 );
116 #if ALIB_DEBUG_ALLOCATIONS
134 "Requested alignment is not a power of 2:",
int(alignment) )
140 char* aligned =
reinterpret_cast<char*
>( (size_t(
act) + alignment - 1) & ~(alignment -1) );
141 if(
size_t(
end - aligned) < dbgSize )
143 act= aligned + dbgSize;
173 constexpr Snapshot( detail:: Buffer* pBuffer,
char* pFill) noexcept
191 {
return buffer !=
nullptr; }
234#if ALIB_DEBUG_MONOMEM
337template<
typename TAllocator>
373 #if ALIB_DEBUG_MONOMEM
380 #if ALIB_DEBUG_CRITICAL_SECTIONS
417 static constexpr size_t MAX_ALIGNMENT = (std::numeric_limits<size_t>::max)();
438 template<
typename TEnableIf= lang::AllocatorMember<TAllocator>,
439 ATMP_T_IF(
int, std::is_default_constructible<TEnableIf>::value )= 0>
468 size_t pInitialBufferSizeInKB,
469 unsigned int pBufferGrowthInPercent= 200 );
471 template<
typename TEnableIf= lang::AllocatorMember<TAllocator>,
472 ATMP_T_IF(
int, std::is_default_constructible<TEnableIf>::value )= 0>
475 size_t pInitialBufferSizeInKB,
476 unsigned int pBufferGrowthInPercent= 200 )
477 :
buffer ( pInitialBuffer )
484 ALIB_ASSERT_ERROR( (
size_t(pInitialBuffer) & (
alignof(
void*)-1) )== 0,
"MONOMEM",
485 "Given initial buffer is not aligned to at least 'alignof(void*)'." )
487 #if ALIB_DEBUG_CRITICAL_SECTIONS
509 TAllocator& pAllocator,
511 size_t pInitialBufferSizeInKB,
512 unsigned int pBufferGrowthInPercent= 200 );
515 TAllocator& pAllocator,
517 size_t pInitialBufferSizeInKB,
518 unsigned int pBufferGrowthInPercent= 200 )
520 ,
buffer ( pInitialBuffer )
527 ALIB_ASSERT_ERROR( (
size_t(pInitialBuffer) & (
alignof(
void*)-1) )== 0,
"MONOMEM",
528 "Given initial buffer is not aligned to at least 'alignof(void*)'." )
530 #if ALIB_DEBUG_CRITICAL_SECTIONS
557 size_t pInitialBufferSizeInKB,
558 unsigned int pBufferGrowthInPercent= 200 );
560 template<
typename TEnableIf= lang::AllocatorMember<TAllocator>,
561 ATMP_T_IF(
int, std::is_default_constructible<TEnableIf>::value )= 0>
563 size_t pInitialBufferSizeInKB,
564 unsigned int pBufferGrowthInPercent= 200 )
571 "MonoAllocator initial buffer of 0kb requested." )
572 size_t initialBufferSize= pInitialBufferSizeInKB * 1024;
573 buffer= new (TAllocator().
allocate(initialBufferSize, alignof(detail::Buffer)))
574 detail::Buffer( initialBufferSize );
575 #if ALIB_DEBUG_CRITICAL_SECTIONS
599 size_t pInitialBufferSizeInKB,
unsigned int pBufferGrowthInPercent= 200 );
603 size_t pInitialBufferSizeInKB,
unsigned int pBufferGrowthInPercent= 200 )
611 "MonoAllocator initial buffer of 0kb requested." )
612 size_t initialBufferSize= pInitialBufferSizeInKB * 1024;
613 buffer= new (TAllocator().
allocate(initialBufferSize, alignof(detail::Buffer)))
614 detail::Buffer( initialBufferSize );
615 #if ALIB_DEBUG_CRITICAL_SECTIONS
667 TAllocator& pAllocator,
668 size_t initialBufferSizeInKB,
673 TAllocator& pAllocator,
674 size_t initialBufferSizeInKB,
696 size_t initialBufferSizeInKB,
703 template<
typename TEnableIf= lang::AllocatorMember<TAllocator>,
704 ATMP_T_IF(
int, std::is_default_constructible<TEnableIf>::value )= 0>
706 size_t initialBufferSizeInKB,
756 inline void*
allocate(
size_t size,
size_t alignment )
758 #if ALIB_DEBUG_CRITICAL_SECTIONS
764 "This MonoAllocator was constructed passing 'nullptr' and is not usable.")
767 "The requested alignment has to be a power of 2. Requested is: ",
int(alignment) )
769 #if ALIB_DEBUG_MONOMEM
771 DBG_ALIGNMENT_INIT(
buffer )
774 #if ALIB_DEBUG_MONOMEM
777 "MonoAllocator: Allocation size exceeds 1/2 of the current buffer size.\n"
778 "The allocator's buffer size should be increased.\n"
779 "Requested size: ",
int(size ) )
786 #if ALIB_DEBUG_MONOMEM
787 DBG_ALIGNMENT_MEASURE(
buffer)
789 #if ALIB_DEBUG_CRITICAL_SECTIONS
796 #if ALIB_DEBUG_CRITICAL_SECTIONS
815 inline void*
reallocate(
void* mem,
size_t oldSize,
size_t newSize,
size_t alignment )
820 "The requested alignment has to be a power of 2. Requested is: ",
int(alignment) )
823 if( oldSize >= newSize )
831 auto* newMem=
allocate( newSize, alignment );
833 std::memcpy( newMem, mem, oldSize );
835 #if ALIB_DEBUG_MONOMEM
851 inline void free(
void* mem,
size_t size)
const
862 template<
typename TSize>
881 #if !ALIB_DEBUG_ALLOCATIONS
940 void Reset(
size_t firstObjectSize,
size_t firstObjectAlignment )
978 template<
typename TSize>
982 #if ALIB_DEBUG_MONOMEM
993 #if ALIB_CAMP && ALIB_DEBUG
1014 extern template ALIB_API class TMonoAllocator<lang::HeapAllocator>;
1022using MonoAllocator = monomem::TMonoAllocator<lang::HeapAllocator>;
constexpr Snapshot(detail::Buffer *pBuffer, char *pFill) noexcept
char * actFill
Pointer to the first free byte in the current buffer.
constexpr Snapshot() noexcept
constexpr bool IsValid() noexcept
detail::Buffer * buffer
The current buffer.
TMonoAllocator(const char *dbgName, size_t pInitialBufferSizeInKB, unsigned int pBufferGrowthInPercent=200)
void * reallocate(void *mem, size_t oldSize, size_t newSize, size_t alignment)
detail::Buffer * recyclables
The list of buffers that are to be recycled.
ALIB_API NAString DbgDumpStatistics()
TMonoAllocator(TMonoAllocator &&)=delete
Not movable.
unsigned int bufferGrowthInPercent
ALIB_API void GetStatistics(Statistics &result)
const DbgStatistics & DbgGetStatistics() const
TMonoAllocator(const char *dbgName, TAllocator &pAllocator, detail::Buffer *pInitialBuffer, size_t pInitialBufferSizeInKB, unsigned int pBufferGrowthInPercent=200)
ALIB_API TMonoAllocator(const char *dbgName, TAllocator &pAllocator, size_t pInitialBufferSizeInKB, unsigned int pBufferGrowthInPercent=200)
void * allocate(size_t size, size_t alignment)
TMonoAllocator(const TMonoAllocator &)=delete
Not copyable.
static constexpr size_t MIN_ALIGNMENT
ALIB_API char * nextBuffer(size_t size, size_t alignment)
TAllocator ChainedAllocator
lang::Placeholder< lang::DbgCriticalSections > DbgCriticalSectionsPH
ALIB_API ~TMonoAllocator()
Destructor. Disposes all memory allocated with ChainedAllocator.
ALIB_API void Reset(Snapshot snapshot=Snapshot())
TMonoAllocator(const char *dbgName, std::nullptr_t) noexcept
TMonoAllocator(const char *dbgName, detail::Buffer *pInitialBuffer, size_t pInitialBufferSizeInKB, unsigned int pBufferGrowthInPercent=200)
void free(void *mem, size_t size) const
bool IsInitialized() const noexcept
size_t nextBuffersUsableSize
ALIB_API void destructWithExternalBuffer()
static TMonoAllocator * Create(const char *dbgName, size_t initialBufferSizeInKB, unsigned int bufferGrowthInPercent=200)
ALIB_FORCE_INLINE void DbgLock(bool onOff) noexcept
void dbgAcknowledgeIncreasedAllocSize(void *, TSize) const
void Reset(size_t firstObjectSize, size_t firstObjectAlignment)
lang::AllocatorMember< TAllocator > allocMember
The allocator type that TAllocator specifies.
static constexpr size_t MAX_ALIGNMENT
lang::AllocatorInterface< TMonoAllocator > operator()()
detail::Buffer * buffer
The actual buffer. Contains a link to previously allocated buffers.
static ALIB_API TMonoAllocator * Create(const char *dbgName, TAllocator &pAllocator, size_t initialBufferSizeInKB, unsigned int bufferGrowthInPercent=200)
constexpr bool allowsMemSplit() noexcept
void dbgCheckMemory(void *mem, TSize size)
#define ALIB_WARNING(...)
#define ALIB_ASSERT_MODULE(modulename)
#define ALIB_WARNINGS_RESTORE
#define ALIB_FORCE_INLINE
#define ALIB_ASSERT_ERROR(cond,...)
#define ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE
#define ALIB_REL_DBG(releaseCode,...)
constexpr int BitCount(TIntegral value)
monomem::TMonoAllocator< lang::HeapAllocator > MonoAllocator
void DbgAssertSingleThreaded()
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)
static constexpr size_t extSize(TIntegral size)
size_t QtyBufferSizeExceeds
The number of allocations that have been larger than the buffer size.
size_t AlignmentWaste
The number of bytes lost for alignment.
size_t QtyResets
The number of resets performed.
size_t QtyAllocationsInclResets
The number of allocations performed, cumulated over resets.
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 QtyAllocations
The number of allocations performed.
size_t QtyTrivialAllocationsInclResets
The number of allocations that did not create a new buffer, cumulated over resets.
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 unsigned char MAGIC
Buffer()=default
Defaulted default constructor.
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.
ALIB_FORCE_INLINE Buffer(size_t size)
static constexpr unsigned char CLEAR
Buffer * previous
the previously allocated buffer.