Using a definite stable version of MEM_BlockAlloc

This commit is contained in:
L 2023-01-30 17:11:44 +01:00
parent 1354224f58
commit a71c6db442
13 changed files with 402 additions and 331 deletions

View file

@ -62,7 +62,7 @@ Event EV_Animate_IsLoopingAnim
EV_RETURN
);
MEM_BlockAlloc< AnimationEvent, MEM_BLOCKSIZE > AnimationEvent_allocator;
MEM_BlockAlloc<AnimationEvent> AnimationEvent_allocator;
void *AnimationEvent::operator new( size_t size )
{

View file

@ -145,7 +145,7 @@ public:
void StopAnimating( Event *ev );
};
extern MEM_BlockAlloc< AnimationEvent, MEM_BLOCKSIZE > AnimationEvent_allocator;
extern MEM_BlockAlloc<AnimationEvent> AnimationEvent_allocator;
inline int Animate::CurrentAnim( int slot )
{

View file

@ -5,7 +5,7 @@
// ConsoleEvent
//===============================
MEM_BlockAlloc< ConsoleEvent, MEM_BLOCKSIZE > ConsoleEvent_allocator;
MEM_BlockAlloc<ConsoleEvent> ConsoleEvent_allocator;
CLASS_DECLARATION(Event, ConsoleEvent, NULL)
{

View file

@ -24,4 +24,4 @@ public:
virtual void ErrorInternal(Listener* l, str text);
};
extern MEM_BlockAlloc< ConsoleEvent, MEM_BLOCKSIZE > ConsoleEvent_allocator;
extern MEM_BlockAlloc<ConsoleEvent> ConsoleEvent_allocator;

View file

@ -127,7 +127,7 @@ void ScriptMaster::Archive( Archiver& arc )
num = ScriptClass_allocator.Count();
arc.ArchiveInteger( &num );
MEM_BlockAlloc_enum< ScriptClass, MEM_BLOCKSIZE > en = ScriptClass_allocator;
MEM_BlockAlloc_enum<ScriptClass> en = ScriptClass_allocator;
for( scr = en.NextElement(); scr != NULL; scr = en.NextElement() )
{
scr->ArchiveInternal( arc );
@ -608,7 +608,7 @@ GameScript *ScriptMaster::GetGameScript( str filename, qboolean recompile )
if( scr && recompile )
{
Container< ScriptClass * > list;
MEM_BlockAlloc_enum< ScriptClass, MEM_BLOCKSIZE > en = ScriptClass_allocator;
MEM_BlockAlloc_enum<ScriptClass> en = ScriptClass_allocator;
ScriptClass *scriptClass;
m_GameScripts[ s ] = NULL;
@ -761,7 +761,7 @@ void ScriptMaster::PrintStatus( void )
int iThreadRunning = 0;
int iThreadWaiting = 0;
int iThreadSuspended = 0;
MEM_BlockAlloc_enum< ScriptClass, MEM_BLOCKSIZE > en = ScriptClass_allocator;
MEM_BlockAlloc_enum<ScriptClass> en = ScriptClass_allocator;
ScriptClass *scriptClass;
char szBuffer[ MAX_STRING_TOKENS ];
@ -820,7 +820,7 @@ void ScriptMaster::PrintThread( int iThreadNum )
ScriptVM *vm;
bool bFoundThread = false;
str status;
MEM_BlockAlloc_enum< ScriptClass, MEM_BLOCKSIZE > en = ScriptClass_allocator;
MEM_BlockAlloc_enum<ScriptClass> en = ScriptClass_allocator;
ScriptClass *scriptClass;
for( scriptClass = en.NextElement(); scriptClass != NULL; scriptClass = en.NextElement() )

View file

@ -2289,7 +2289,7 @@ CLASS_DECLARATION( Listener, ScriptThread, NULL )
{ NULL, NULL }
};
MEM_BlockAlloc< ScriptThread, MEM_BLOCKSIZE > ScriptThread_allocator;
MEM_BlockAlloc<ScriptThread> ScriptThread_allocator;
void *ScriptThread::operator new( size_t size )
{

View file

@ -53,7 +53,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// ScriptClass
//====================
MEM_BlockAlloc< ScriptClass, MEM_BLOCKSIZE > ScriptClass_allocator;
MEM_BlockAlloc<ScriptClass> ScriptClass_allocator;
CLASS_DECLARATION(Listener, ScriptClass, NULL)
{
@ -426,7 +426,7 @@ Listener* ScriptClass::GetSelf()
//====================
MEM_BlockAlloc< ScriptVM, char[256] > ScriptVM_allocator;
MEM_BlockAlloc<ScriptVM> ScriptVM_allocator;
/*
====================

View file

@ -325,6 +325,6 @@ public:
bool CanScriptTracePrint( void );
};
extern MEM_BlockAlloc< ScriptClass, MEM_BLOCKSIZE > ScriptClass_allocator;
extern MEM_BlockAlloc<ScriptClass> ScriptClass_allocator;
#endif

View file

@ -125,6 +125,13 @@ extern "C" {
if( node->next ) node->next->prev = node->prev; \
}
#define LL_SafeRemoveRoot(rootnode,node,next,prev) \
{ \
if (rootnode == node) rootnode = (node->next); \
if (node->prev) node->prev->next = node->next; \
if (node->next) node->next->prev = node->prev; \
}
#define LL_SafeAdd(rootnode, newnode, next, prev) \
{ \
(newnode)->next = NULL; \

View file

@ -69,7 +69,7 @@ class con_set
friend class con_set_enum < k, v > ;
public:
static MEM_BlockAlloc< Entry< k, v >, MEM_BLOCKSIZE > Entry_allocator;
static MEM_BlockAlloc<Entry<k, v >> Entry_allocator;
protected:
Entry< k, v > **table; // hashtable
@ -187,7 +187,7 @@ int HashCode( const str& key );
*/
template< typename k, typename v >
MEM_BlockAlloc< Entry< k, v >, MEM_BLOCKSIZE > con_set< k, v >::Entry_allocator;
MEM_BlockAlloc<Entry< k, v >> con_set< k, v >::Entry_allocator;
template< typename k >
int HashCode( const k& key );

View file

@ -1149,7 +1149,7 @@ void EventDef::SetupDocumentation( void )
// Event
//====================================
MEM_BlockAlloc< Event, MEM_BLOCKSIZE > Event_allocator;
MEM_BlockAlloc<Event> Event_allocator;
CLASS_DECLARATION( Class, Event, NULL )
{

View file

@ -608,7 +608,7 @@ extern cvar_t *g_timeevents;
extern cvar_t *g_watch;
extern cvar_t *g_eventstats;
extern MEM_BlockAlloc< Event, MEM_BLOCKSIZE > Event_allocator;
extern MEM_BlockAlloc<Event> Event_allocator;
#if defined( GAME_DLL )
//

View file

@ -26,482 +26,546 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define __MEM_BLOCKALLOC_H__
#include "linklist.h"
#define MEM_BLOCKSIZE char[ 256 ]
#include "q_shared.h"
void *MEM_Alloc( int size );
void MEM_Free( void *ptr );
template< typename aclass, typename blocksize >
static constexpr size_t DefaultBlock = 256;
enum class alloc_source_e
{
SourceBlock = 174,
SourceMalloc
};
template<typename aclass, size_t blocksize>
class MEM_BlockAlloc_enum;
template< typename aclass, typename blocksize >
template<typename aclass, size_t blocksize>
class block_s {
public:
#ifndef _DEBUG_MEMBLOCK
unsigned char data[ sizeof( blocksize ) ][ sizeof( aclass ) + 8 ];
unsigned char prev_data[ sizeof( blocksize ) ];
unsigned char next_data[ sizeof( blocksize ) ];
short int free_data;
short int used_data;
#else
unsigned char data[ sizeof( aclass ) ];
#endif
block_s< aclass, blocksize > *prev_block;
block_s< aclass, blocksize > *next_block;
};
template< typename aclass, typename blocksize >
class MEM_BlockAlloc {
friend class MEM_BlockAlloc_enum< aclass, blocksize >;
#ifndef _DEBUG_MEMBLOCK
// Free block list [not usable], avoid slow down by using gi.Free
block_s< aclass, blocksize > *m_FreeBlock;
// Starting block list that will be used for further memory allocation
block_s< aclass, blocksize > *m_StartUsedBlock;
// Full block list [not usable], no space available for further memory allocation
block_s< aclass, blocksize > *m_StartFullBlock;
#else
block_s< aclass, blocksize > *m_Block;
#endif
unsigned int m_BlockCount;
private:
unsigned int Count( block_s< aclass, blocksize > *block );
static constexpr size_t bitsNeeded =
blocksize <= 0x80 ? 8 :
blocksize <= 0x8000 ? 16 :
blocksize <= 0x80000000 ? 32 :
64;
public:
MEM_BlockAlloc();
block_s();
void *Alloc( void );
void Free( void *ptr );
void FreeAll( void );
unsigned int Count( void );
unsigned int BlockCount( void );
unsigned int BlockMemory( void );
};
template< typename aclass, typename blocksize >
class MEM_BlockAlloc_enum {
protected:
MEM_BlockAlloc< aclass, blocksize > *m_Owner;
block_s< aclass, blocksize > *m_CurrentBlock;
#ifndef _DEBUG_MEMBLOCK
unsigned char m_CurrentData;
int m_CurrentBlockType;
#if !_DEBUG_MEMBLOCK
bool usedDataAvailable() const;
bool freeDataAvailable() const;
#endif
public:
MEM_BlockAlloc_enum( MEM_BlockAlloc< aclass, blocksize >& owner );
template<size_t bits>
struct selectType_t;
aclass *NextElement( void );
aclass *CurrentElement( void );
};
template<> struct selectType_t<8> { using type = uint8_t; };
template<> struct selectType_t<16> { using type = uint16_t; };
template<> struct selectType_t<32> { using type = uint32_t; };
template<> struct selectType_t<64> { using type = uint64_t; };
template< typename a, typename b >
MEM_BlockAlloc< a, b >::MEM_BlockAlloc( void )
{
#ifndef _DEBUG_MEMBLOCK
m_FreeBlock = NULL;
m_StartUsedBlock = NULL;
m_StartFullBlock = NULL;
m_BlockCount = 0;
using offset_t = typename selectType_t<bitsNeeded>::type;
struct info_t {
offset_t index;
alloc_source_e source;
static constexpr uint16_t typeSize = sizeof(aclass);
alignas(alignof(aclass)) char data[sizeof(aclass)];
};
public:
#if !_DEBUG_MEMBLOCK
info_t data[blocksize];
offset_t prev_data[blocksize];
offset_t next_data[blocksize];
offset_t free_data;
offset_t used_data;
bool has_free_data : 1;
bool has_used_data : 1;
#else
m_Block = NULL;
offset_t data[sizeof(aclass)];
#endif
block_s<aclass, blocksize>* prev_block;
block_s<aclass, blocksize>* next_block;
public:
static constexpr size_t headersize = offsetof(info_t, data);
static constexpr size_t dataoffset = 0;
static constexpr size_t datasize = sizeof(info_t);
};
template<typename aclass, size_t blocksize>
block_s<aclass, blocksize>::block_s()
#if !_DEBUG_MEMBLOCK
{
info_t* header;
offset_t curr;
for (curr = 0; curr < blocksize - 1; ++curr)
{
offset_t next = curr + 1;
header = &data[curr];
header->source = alloc_source_e::SourceBlock;
header->index = curr;
prev_data[next] = curr;
next_data[curr] = next;
}
header = &data[curr];
header->source = alloc_source_e::SourceBlock;
header->index = blocksize - 1;
prev_data[0] = blocksize - 1;
next_data[blocksize - 1] = 0;
free_data = 0;
prev_block = next_block = nullptr;
has_free_data = true;
has_used_data = false;
}
#else
: prev_block(nullptr)
, next_block(nullptr)
{
}
#endif
#if !_DEBUG_MEMBLOCK
template<typename aclass, size_t blocksize>
bool block_s<aclass, blocksize>::usedDataAvailable() const {
return has_used_data;
}
template< typename a, typename b >
void *MEM_BlockAlloc< a, b >::Alloc( void )
{
#ifdef _DEBUG_MEMBLOCK
block_s<a, b> *block = ( block_s<a, b> * )malloc( sizeof( block_s <a, b> ) );
template<typename aclass, size_t blocksize>
bool block_s<aclass, blocksize>::freeDataAvailable() const {
return has_free_data;
}
#endif
LL_SafeAddFirst( m_Block, block, next_block, prev_block );
template<typename aclass, size_t blocksize = DefaultBlock>
class MEM_BlockAlloc
{
static_assert(blocksize >= 2, "Minimum 2x class preallocation required!!");
public:
MEM_BlockAlloc();
~MEM_BlockAlloc();
void* Alloc();
void Free(void* ptr) noexcept;
void FreeAll() noexcept;
size_t Count();
size_t BlockCount();
size_t BlockMemory();
private:
friend class MEM_BlockAlloc_enum<aclass, blocksize>;
using block_t = block_s<aclass, blocksize>;
using block_offset_t = typename block_t::offset_t;
#if !_DEBUG_MEMBLOCK
block_t* m_FreeBlock;
block_t* m_StartUsedBlock;
block_t* m_StartFullBlock;
#else
block_t* m_Block;
#endif
size_t m_BlockCount;
private:
void* TakeFree(block_t* block, uintptr_t free_data);
size_t Count(const block_t* block);
};
template<typename aclass, size_t blocksize = DefaultBlock>
class MEM_BlockAlloc_enum
{
public:
MEM_BlockAlloc_enum(MEM_BlockAlloc<aclass, blocksize>& owner);
aclass* NextElement();
aclass* CurrentElement();
enum blockType_e {
used,
full
};
private:
using block_t = block_s<aclass, blocksize>;
using offset_t = typename block_t::offset_t;
MEM_BlockAlloc<aclass, blocksize>* m_Owner;
block_t* m_CurrentBlock;
#if !_DEBUG_MEMBLOCK
offset_t m_CurrentData;
blockType_e m_CurrentBlockType;
#endif
};
template<typename a, size_t b>
MEM_BlockAlloc<a, b>::MEM_BlockAlloc()
#if !_DEBUG_MEMBLOCK
: m_StartUsedBlock()
, m_StartFullBlock()
{
m_FreeBlock = nullptr;
m_BlockCount = 0;
}
#else
: m_Block()
{
m_BlockCount = 0;
}
#endif
template<typename a, size_t b>
MEM_BlockAlloc<a, b>::~MEM_BlockAlloc()
{
FreeAll();
}
template<typename a, size_t b>
void* MEM_BlockAlloc<a, b>::Alloc()
{
#if _DEBUG_MEMBLOCK
block_t* block = new(MEM_Alloc(sizeof(block_t))) block_t();
m_Block.AddFirst(block);
m_BlockCount++;
return ( void * )block->data;
return (void*)block->data;
#else
unsigned char i;
block_s< a, b > *block;
block_s< a, b > *used_block;
short int free_data;
short int used_data;
unsigned char prev_data;
unsigned char next_data;
block_t* used_block;
block_offset_t free_data;
block_offset_t next_data;
block = m_StartUsedBlock;
if( block )
if (m_StartUsedBlock)
{
used_block = m_StartUsedBlock;
free_data = used_block->free_data;
next_data = used_block->next_data[ free_data ];
next_data = used_block->next_data[free_data];
if( next_data == free_data )
if (next_data == free_data)
{
// Move the block to the full block list as there is no space available
m_StartUsedBlock = block->next_block;
// Move the block to the next block list as there is no space available
m_StartUsedBlock = used_block->next_block;
LL_SafeRemove( block, next_block, prev_block );
LL_SafeAddFirst( m_StartFullBlock, used_block, next_block, prev_block );
LL_SafeRemoveRoot(m_StartUsedBlock, used_block, next_block, prev_block);
LL_SafeAddFirst(m_StartFullBlock, used_block, next_block, prev_block);
used_block->free_data = -1;
goto _ret;
used_block->has_free_data = false;
return TakeFree(used_block, free_data);
}
}
else
{
block = m_FreeBlock;
if( block )
if (m_FreeBlock)
{
m_FreeBlock = NULL;
used_block = block;
free_data = block->free_data;
next_data = block->next_data[ free_data ];
// start from the free block
used_block = m_FreeBlock;
m_FreeBlock = nullptr;
free_data = used_block->free_data;
next_data = used_block->next_data[free_data];
}
else
{
m_BlockCount++;
used_block = ( block_s< a, b > * )MEM_Alloc( sizeof( block_s< a, b > ) );
for( i = sizeof( b ) - 1; i; i-- )
{
unsigned char prev = i - 1;
unsigned char next = prev + 1;
used_block->data[ prev ][ 0 ] = -82;
used_block->data[ prev ][ 1 ] = prev;
*( short * )( &used_block->data[ prev ][ 2 ] ) = sizeof( a );
used_block->prev_data[ next ] = prev;
used_block->next_data[ prev ] = next;
}
used_block->data[ sizeof( b ) - 1 ][ 0 ] = -82;
used_block->data[ sizeof( b ) - 1 ][ 1 ] = -1;
*( short * )( &used_block->data[ sizeof( b ) - 1 ][ 2 ] ) = sizeof( a );
used_block->prev_data[ 0 ] = -1;
used_block->next_data[ sizeof( b ) - 1 ] = 0;
used_block->free_data = 0;
used_block->used_data = -1;
// allocate and construct a new block
used_block = new(MEM_Alloc(sizeof(block_t))) block_t();
free_data = 0;
next_data = 1;
}
LL_SafeAddFirst( m_StartUsedBlock, used_block, next_block, prev_block );
LL_SafeAddFirst(m_StartUsedBlock, used_block, next_block, prev_block);
}
prev_data = used_block->prev_data[ free_data ];
used_block->next_data[ prev_data ] = next_data;
used_block->prev_data[ next_data ] = prev_data;
used_block->free_data = next_data;
const block_offset_t prev_data = used_block->prev_data[free_data];
if( used_block->used_data < 0 )
used_block->next_data[prev_data] = next_data;
used_block->prev_data[next_data] = prev_data;
used_block->free_data = next_data;
used_block->has_free_data = true;
if (!used_block->usedDataAvailable())
{
used_block->used_data = free_data;
used_block->next_data[ free_data ] = free_data;
used_block->prev_data[ free_data ] = free_data;
return ( void * )&used_block->data[ free_data ][ 8 ];
used_block->has_used_data = true;
used_block->next_data[free_data] = free_data;
used_block->prev_data[free_data] = free_data;
return used_block->data[free_data].data;
}
_ret:
used_data = used_block->used_data;
prev_data = used_block->prev_data[ used_data ];
used_block->prev_data[ used_data ] = free_data;
used_block->next_data[ prev_data ] = free_data;
used_block->prev_data[ free_data ] = prev_data;
used_block->next_data[ free_data ] = used_data;
return ( void * )&used_block->data[ free_data ][ 8 ];
return TakeFree(used_block, free_data);
#endif
}
template< typename a, typename b >
void MEM_BlockAlloc< a, b >::Free( void *ptr )
template< typename aclass, size_t blocksize>
void* MEM_BlockAlloc<aclass, blocksize>::TakeFree(block_t* block, uintptr_t free_data)
{
#ifdef _DEBUG_MEMBLOCK
block_s<a, b> *block = ( block_s<a, b> * )ptr;
const block_offset_t used_data = block->used_data;
const block_offset_t prev_data = block->prev_data[used_data];
assert( m_Block );
LL_SafeRemove( block, next_block, prev_block );
block->next_data[prev_data] = (block_offset_t)free_data;
block->prev_data[used_data] = (block_offset_t)free_data;
block->next_data[free_data] = used_data;
block->prev_data[free_data] = prev_data;
return block->data[free_data].data;
}
if( m_Block == block )
{
m_Block = block->next_block;
}
template<typename a, size_t b>
void MEM_BlockAlloc<a, b>::Free(void* ptr) noexcept
{
#if _DEBUG_MEMBLOCK
block_s<a, b>* block = (block_s<a, b> *)ptr;
m_Block.Remove(block);
m_BlockCount--;
free( block );
MEM::Free(block);
#else
block_s< a, b > *block;
short int free_data;
short int used_data;
unsigned char prev_data;
unsigned char next_data;
used_data = *( ( unsigned char * )ptr - 7 );
block = ( block_s< a, b > * )( ( unsigned char * )ptr + -( used_data * ( *( ( unsigned short * )ptr - 3 ) + 8 ) ) - 8 );
next_data = block->next_data[ used_data ];
if( next_data == used_data )
// get the header of the pointer
typename block_t::info_t* header = reinterpret_cast<typename block_t::info_t*>(static_cast<unsigned char*>(ptr) - block_t::headersize);
const block_offset_t used_data = header->index;
// get the block from the header
block_t* const block = (block_t*)((uint8_t*)header - used_data * block_t::datasize - block_t::dataoffset);
const block_offset_t next_data = block->next_data[used_data];
if (next_data == used_data)
{
if( m_StartUsedBlock == block )
{
m_StartUsedBlock = block->next_block;
}
LL_SafeRemoveRoot(m_StartUsedBlock, block, next_block, prev_block);
LL_SafeRemove( block, next_block, prev_block );
if( m_FreeBlock )
if (m_FreeBlock)
{
m_BlockCount--;
MEM_Free( m_FreeBlock );
m_FreeBlock = NULL;
// deallocate the free block because of another deallocation
--m_BlockCount;
MEM_Free(m_FreeBlock);
m_FreeBlock = nullptr;
}
m_FreeBlock = block;
block->used_data = -1;
block->has_used_data = false;
free_data = block->free_data;
prev_data = block->prev_data[ free_data ];
const block_offset_t free_data = block->free_data;
const block_offset_t prev_data = block->prev_data[free_data];
block->next_data[ prev_data ] = used_data;
block->prev_data[ free_data ] = used_data;
block->next_data[ used_data ] = free_data;
block->prev_data[ used_data ] = prev_data;
return;
block->next_data[prev_data] = used_data;
block->prev_data[free_data] = used_data;
block->next_data[used_data] = free_data;
block->prev_data[used_data] = prev_data;
}
prev_data = block->prev_data[ used_data ];
block->next_data[ prev_data ] = next_data;
block->prev_data[ next_data ] = prev_data;
block->used_data = next_data;
if( block->free_data >= 0 )
else
{
free_data = block->free_data;
prev_data = block->prev_data[ free_data ];
const block_offset_t prev_data = block->prev_data[used_data];
block->next_data[ prev_data ] = used_data;
block->prev_data[ free_data ] = used_data;
block->next_data[ used_data ] = free_data;
block->prev_data[ used_data ] = prev_data;
return;
block->next_data[prev_data] = next_data;
block->prev_data[next_data] = prev_data;
block->used_data = next_data;
block->has_used_data = true;
if (block->freeDataAvailable())
{
const block_offset_t free_data = block->free_data;
const block_offset_t prev_data = block->prev_data[free_data];
block->next_data[prev_data] = used_data;
block->prev_data[free_data] = used_data;
block->next_data[used_data] = free_data;
block->prev_data[used_data] = prev_data;
return;
}
if (m_StartFullBlock == block)
{
m_StartFullBlock = block->next_block;
}
LL_SafeRemoveRoot(m_StartFullBlock, block, next_block, prev_block);
LL_SafeAddFirst(m_StartUsedBlock, block, next_block, prev_block);
block->free_data = used_data;
block->has_free_data = true;
block->prev_data[used_data] = used_data;
block->next_data[used_data] = used_data;
}
if( m_StartFullBlock == block )
{
m_StartFullBlock = block->next_block;
}
LL_SafeRemove( block, next_block, prev_block );
LL_SafeAddFirst( m_StartUsedBlock, block, next_block, prev_block );
block->prev_data[ used_data ] = used_data;
block->next_data[ used_data ] = used_data;
block->free_data = used_data;
#endif
}
template< typename a, typename b >
void MEM_BlockAlloc< a, b >::FreeAll( void )
template<typename a, size_t b>
void MEM_BlockAlloc<a, b>::FreeAll() noexcept
{
#ifdef _DEBUG_MEMBLOCK
block_s<a, b> *block;
block_s<a, b> *next = m_Block;
for( block = m_Block; next != NULL; block = next )
#if _DEBUG_MEMBLOCK
block_t* block;
block_t* next = m_Block.Root();
for (block = next; block; block = next)
{
next = block->next_block;
m_BlockCount--;
a *ptr = ( a * )block->data;
a* ptr = (a*)block->data;
ptr->~a();
free( block );
MEM::Free(block);
}
m_Block = NULL;
m_Block.Reset();
#else
block_s< a, b > *block;
block = m_StartFullBlock;
while( block )
while(block_t* b = m_StartFullBlock)
{
if( block->used_data >= 0 )
if (b->usedDataAvailable())
{
a *ptr = ( a * )&block->data[ block->used_data ][ 8 ];
delete ptr;
block = m_StartFullBlock;
a* ptr = (a*)b->data[b->used_data].data;
ptr->~a();
Free(ptr);
b = m_StartFullBlock;
}
}
block = m_StartUsedBlock;
while( block )
while (block_t* b = m_StartUsedBlock)
{
if( block->used_data >= 0 )
if (b->usedDataAvailable())
{
a *ptr = ( a * )&block->data[ block->used_data ][ 8 ];
delete ptr;
block = m_StartUsedBlock;
a* ptr = (a*)b->data[b->used_data].data;
ptr->~a();
Free(ptr);
}
}
if( m_FreeBlock )
if (m_FreeBlock)
{
m_BlockCount--;
MEM_Free( m_FreeBlock );
m_FreeBlock = NULL;
MEM_Free(m_FreeBlock);
m_FreeBlock = nullptr;
}
#endif
}
template< typename a, typename b >
unsigned int MEM_BlockAlloc< a, b >::Count( block_s< a, b > *block )
template<typename a, size_t b>
size_t MEM_BlockAlloc<a, b>::Count(const block_t* list)
{
int count = 0;
#ifdef _DEBUG_MEMBLOCK
for( ; block != NULL; block = block->next_block )
#if _DEBUG_MEMBLOCK
for (const block_t* block = list; block; block = block->next_block)
{
count++;
}
return count;
#else
unsigned char used_data;
unsigned char current_used_data;
for( ; block != NULL; block = block->next_block )
for (const block_t* block = list; block; block = block->next_block)
{
used_data = block->used_data;
if( used_data < 0 )
if (!block->usedDataAvailable())
{
continue;
}
current_used_data = used_data;
const block_offset_t used_data = block->used_data;
block_offset_t current_used_data = used_data;
do
{
count++;
current_used_data = block->next_data[ current_used_data ];
} while( current_used_data != used_data );
current_used_data = block->next_data[current_used_data];
} while (current_used_data != used_data);
}
return count;
#endif
}
template< typename a, typename b >
unsigned int MEM_BlockAlloc< a, b >::Count( void )
template<typename a, size_t b>
size_t MEM_BlockAlloc<a, b>::Count()
{
#ifdef _DEBUG_MEMBLOCK
return Count( m_Block );
#if _DEBUG_MEMBLOCK
return Count(m_Block);
#else
return Count( m_StartFullBlock ) + Count( m_StartUsedBlock );
return Count(m_StartFullBlock) + Count(m_StartUsedBlock);
#endif
}
template< typename a, typename b >
unsigned int MEM_BlockAlloc< a, b >::BlockCount( void )
template<typename a, size_t b>
size_t MEM_BlockAlloc<a, b>::BlockCount()
{
return m_BlockCount;
}
template< typename a, typename b >
unsigned int MEM_BlockAlloc< a, b >::BlockMemory( void )
template<typename a, size_t b>
size_t MEM_BlockAlloc<a, b>::BlockMemory()
{
return sizeof( block_s< a, b > );
return sizeof(block_s<a, b>);
}
template< typename a, typename b >
MEM_BlockAlloc_enum< a, b >::MEM_BlockAlloc_enum( MEM_BlockAlloc< a, b >& owner )
template<typename a, size_t b>
MEM_BlockAlloc_enum<a, b >::MEM_BlockAlloc_enum(MEM_BlockAlloc< a, b>& owner)
{
m_Owner = &owner;
m_CurrentBlock = NULL;
#ifndef _DEBUG_MEMBLOCK
m_CurrentBlockType = 0;
m_CurrentBlock = nullptr;
#if !_DEBUG_MEMBLOCK
m_CurrentBlockType = MEM_BlockAlloc_enum::used;
#endif
}
template< typename a, typename b >
a *MEM_BlockAlloc_enum< a, b >::NextElement( void )
template<typename a, size_t b>
a* MEM_BlockAlloc_enum<a, b>::NextElement()
{
#ifdef _DEBUG_MEMBLOCK
if( !m_CurrentBlock )
#if _DEBUG_MEMBLOCK
if (!m_CurrentBlock)
{
m_CurrentBlock = m_Owner->m_Block;
m_CurrentBlock = m_Owner->m_Block.Root();
}
else
{
m_CurrentBlock = m_CurrentBlock->next_block;
}
return ( a * )m_CurrentBlock;
return (a*)m_CurrentBlock;
#else
block_s< a, b > *block;
block_s< a, b > *next;
block = m_CurrentBlock;
if( block )
// search for a valid block type
while (!m_CurrentBlock)
{
m_CurrentData = block->next_data[ m_CurrentData ];
if( m_CurrentData == block->used_data )
switch (m_CurrentBlockType)
{
block = m_CurrentBlock = block->next_block;
case blockType_e::used:
m_CurrentBlock = m_Owner->m_StartUsedBlock;
break;
case blockType_e::full:
m_CurrentBlock = m_Owner->m_StartFullBlock;
break;
default:
return nullptr;
}
reinterpret_cast<uint8_t&>(m_CurrentBlockType)++;
_label:
for (; m_CurrentBlock; m_CurrentBlock = m_CurrentBlock->next_block)
{
if (m_CurrentBlock->usedDataAvailable())
{
m_CurrentData = m_CurrentBlock->used_data;
return reinterpret_cast<a*>(m_CurrentBlock->data[m_CurrentData].data);
}
}
}
if( !block )
m_CurrentData = m_CurrentBlock->next_data[m_CurrentData];
if (m_CurrentData == m_CurrentBlock->used_data)
{
while( !block )
{
while( !block )
{
if( m_CurrentBlockType == 0 )
{
block = m_Owner->m_StartFullBlock;
}
else if( m_CurrentBlockType == 1 )
{
block = m_Owner->m_StartUsedBlock;
}
else
{
return NULL;
}
m_CurrentBlock = block;
m_CurrentBlockType++;
}
while( block->used_data < 0 )
{
next = block->next_block;
block = NULL;
m_CurrentBlock = next;
if( !next )
{
break;
}
block = next;
}
}
m_CurrentData = block->used_data;
// found an object
m_CurrentBlock = m_CurrentBlock->next_block;
goto _label;
}
return ( a * )&block->data[ m_CurrentData ][ 8 ];
return reinterpret_cast<a*>(m_CurrentBlock->data[m_CurrentData].data);
#endif
}
template< typename a, typename b >
a *MEM_BlockAlloc_enum< a, b >::CurrentElement( void )
template<typename a, size_t b>
a* MEM_BlockAlloc_enum<a, b>::CurrentElement()
{
return m_CurrentBlock;
}