//- 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; }