vn/code/core/core_memory.cpp

153 lines
3.8 KiB
C++

//- sixten: Common memory functions
static void Copy(void *Dest, void *Source, umm Count)
{
u8 *Dest8 = (u8 *)Dest;
u8 *Source8 = (u8 *)Source;
while(Count--)
{
*Dest8++ = *Source8++;
}
}
static void Fill(void *Dest, u8 Value, umm Count)
{
u8 *Dest8 = (u8 *)Dest;
while(Count--)
{
*Dest8++ = Value;
}
}
//- sixten: Memory arena functions
static void Release(memory_arena *Arena)
{
while(Arena->CurrentBlock != 0)
{
platform_memory_block *MemoryBlock = Arena->CurrentBlock;
b32 IsLastBlock = (MemoryBlock->ArenaPrev == 0);
Arena->CurrentBlock = MemoryBlock->ArenaPrev;
Platform.DeallocateMemory(MemoryBlock);
if(IsLastBlock)
{
break;
}
}
}
inline umm GetAlignmentOffset(memory_arena *Arena, umm Alignment)
{
umm AlignmentOffset = 0;
umm ResultPointer = (umm)Arena->CurrentBlock + Arena->CurrentBlock->Used;
umm AlignmentMask = Alignment - 1;
if(ResultPointer & AlignmentMask)
{
AlignmentOffset = Alignment - (ResultPointer & AlignmentMask);
}
return(AlignmentOffset);
}
inline umm GetEffectiveSizeFor(memory_arena *Arena, umm InitialSize, arena_push_params Params)
{
umm Size = InitialSize;
umm AlignmentOffset = GetAlignmentOffset(Arena, Params.Alignment);
Size += AlignmentOffset;
return(Size);
}
static void *PushSize_(memory_arena *Arena, umm InitialSize, arena_push_params Params)
{
void *Result = 0;
umm Size = 0;
if(Arena->CurrentBlock)
{
Size = GetEffectiveSizeFor(Arena, InitialSize, Params);
}
if(!Arena->CurrentBlock || ((Arena->CurrentBlock->Used + Size) > Arena->CurrentBlock->Size))
{
Size = InitialSize;
if(!Arena->MinimumBlockSize)
{
Arena->MinimumBlockSize = 1024*1024;
}
umm BlockSize = Maximum(Size, Arena->MinimumBlockSize);
platform_memory_block *NewBlock = Platform.AllocateMemory(BlockSize);
NewBlock->ArenaPrev = Arena->CurrentBlock;
Arena->CurrentBlock = NewBlock;
}
Assert((Arena->CurrentBlock->Used + Size) <= Arena->CurrentBlock->Size);
umm AlignmentOffset = GetAlignmentOffset(Arena, Params.Alignment);
umm OffsetInBlock = Arena->CurrentBlock->Used + AlignmentOffset;
Result = Arena->CurrentBlock->Base + OffsetInBlock;
Arena->CurrentBlock->Used += Size;
Assert(Size >= InitialSize);
Assert(Arena->CurrentBlock->Used <= Arena->CurrentBlock->Size);
if(Params.Flags & ArenaFlag_ClearToZero)
{
Fill(Result, 0, InitialSize);
}
return(Result);
}
//- sixten: Bootsrapping helpers
static void *BootstrapPushSize(umm Size, umm OffsetToArena)
{
memory_arena Arena = {};
void *Result = PushSize(&Arena, Size);
*(memory_arena *)((u8 *)Result + OffsetToArena) = Arena;
return(Result);
}
//- sixten: Temporary memory functions
static temporary_memory BeginTemporaryMemory(memory_arena *Arena)
{
temporary_memory Result;
Result.Arena = Arena;
Result.Block = Arena->CurrentBlock;
Result.Used = Arena->CurrentBlock ? Arena->CurrentBlock->Used : 0;
++Arena->TemporaryMemoryCount;
return(Result);
}
static void EndTemporaryMemory(temporary_memory Temp)
{
memory_arena *Arena = Temp.Arena;
while(Arena->CurrentBlock != Temp.Block)
{
platform_memory_block *MemoryBlock = Arena->CurrentBlock;
Arena->CurrentBlock = MemoryBlock->ArenaPrev;
Platform.DeallocateMemory(MemoryBlock);
}
if(Arena->CurrentBlock)
{
Assert(Arena->CurrentBlock->Used >= Temp.Used);
Arena->CurrentBlock->Used = Temp.Used;
}
Assert(Arena->TemporaryMemoryCount > 0);
--Arena->TemporaryMemoryCount;
}