+++ /dev/null
-#ifndef VG_MEM_H
-#define VG_MEM_H
-
-#include "vg.h"
-#include "vg_stdint.h"
-#include "vg_platform.h"
-
-#include <stdlib.h>
-#include <malloc.h>
-
-#define VG_MAX_ALLOCATIONS 64
-#define VG_FUZZ_ALLOCATIONS
-
-typedef struct vg_linear_allocator vg_linear_allocator;
-typedef struct vg_allocation_meta vg_allocation_meta;
-
-struct
-{
- void *rtmemory,
- *scratch;
-
- int use_libc_malloc;
- u32 quota;
-}
-static vg_mem;
-
-struct vg_allocation_meta
-{
- void *data;
- enum allocation_type
- {
- k_allocation_type_block = 0,
- k_allocation_type_linear = 1
- }
- type;
-};
-
-#define VG_MEMORY_SYSTEM 0x1 /* systems memory, slow and low counts */
-#define VG_MEMORY_REALTIME 0x2 /* per-frame. no max allocs, only size. fast */
-
-/* systems memory cannot be declared inside realtime memory regions */
-
-/*
- * Stored just behind the array. 32 bytes.
- */
-#pragma pack(push,1)
-struct vg_linear_allocator
-{
- u32 size;
- /* */
- /* */
- /* */
- u32 cur;
- /* */
- /* */
- /* */
- u16 allocation_count;
- /* */
- u16 flags;
- /* */
- u32 last_alloc_size;
- /* */
- /* */
- /* */
- void *last_alloc;
- /* */
- /* */
- /* */
- /* */
- /* */
- /* */
- /* */
- vg_allocation_meta *alloc_table;
- /* */
- /* */
- /* */
- /* */
- /* */
- /* */
- /* */
-
-#ifdef _WIN32
- /* 32 bit pointers! */
- u8 padding[ 8 ];
-#endif
-};
-#pragma pack(pop)
-
-VG_STATIC void vg_fatal_exit_loop( const char *error );
-VG_STATIC void vg_error(const char *fmt, ...);
-VG_STATIC void vg_info(const char *fmt, ...);
-
-/* Returns allocator structure from data pointer */
-static vg_linear_allocator *vg_linear_header( void *data )
-{
- vg_linear_allocator *ptr = data;
- ptr --;
-
- return ptr;
-}
-
-/* allocate something from a linear allocator */
-__attribute__((warn_unused_result))
-VG_STATIC void *vg_linear_alloc( void *buffer, u32 size )
-{
- vg_linear_allocator *alloc = vg_linear_header( buffer );
-
- if( (alloc->cur + size) > alloc->size )
- {
- vg_error( "%u + %u > %u\n", alloc->cur, size, alloc->size );
- vg_fatal_exit_loop( "linear allocator overflow" );
- }
-
- if( alloc->flags & VG_MEMORY_SYSTEM )
- if( (alloc->allocation_count + 1) > VG_MAX_ALLOCATIONS )
- vg_fatal_exit_loop( "Max linear allocations reached" );
-
- void *data;
-
- if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) )
- {
- data = malloc( size );
-
- vg_allocation_meta *meta = &alloc->alloc_table[ alloc->allocation_count ];
- meta->type = k_allocation_type_block;
- meta->data = data;
- }
- else
- {
- data = buffer + alloc->cur;
- }
-
- alloc->allocation_count ++;
- alloc->last_alloc = data;
- alloc->last_alloc_size = size;
- alloc->cur += size;
-
- return data;
-}
-
-
-/* resize latest block of memory from linear */
-__attribute__((warn_unused_result))
-VG_STATIC void *vg_linear_resize( void *buffer, void *data, u32 newsize )
-{
- vg_linear_allocator *alloc = vg_linear_header( buffer );
-
- if( alloc->last_alloc != data )
- vg_fatal_exit_loop( "This block has been fixed!" );
-
- if( (alloc->cur - alloc->last_alloc_size + newsize) > alloc->size )
- vg_fatal_exit_loop( "Cannot resize, overflow" );
-
- alloc->cur -= alloc->last_alloc_size;
- alloc->cur += newsize;
- alloc->last_alloc_size = newsize;
-
- if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) )
- {
- data = realloc( data, newsize );
- if( !data )
- vg_fatal_exit_loop( "realloc failed" );
-
- alloc->alloc_table[ alloc->allocation_count-1 ].data = data;
- alloc->last_alloc = data;
- return data;
- }
- else
- {
- return data;
- }
-}
-
-/* its possible to delete just the last item */
-VG_STATIC void vg_linear_del( void *buffer, void *data )
-{
- vg_linear_allocator *alloc = vg_linear_header( buffer );
-
- if( alloc->last_alloc != data )
- vg_fatal_exit_loop( "This block has been fixed!" );
-
- if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) )
- {
- vg_allocation_meta *meta = &alloc->alloc_table[alloc->allocation_count-1];
- if( meta->type == k_allocation_type_linear )
- vg_fatal_exit_loop( "Cannot free a linear allocator in this conext" );
-
- free( data );
- }
-
- alloc->allocation_count --;
- alloc->cur -= alloc->last_alloc_size;
- alloc->last_alloc = NULL;
- alloc->last_alloc_size = 0;
-}
-
-/* extend latest block of memory from linear */
-__attribute__((warn_unused_result))
-VG_STATIC void *vg_linear_extend( void *buffer, void *data, u32 extra )
-{
- vg_linear_allocator *alloc = vg_linear_header( buffer );
-
- if( alloc->last_alloc != data )
- vg_fatal_exit_loop( "This block has been fixed!" );
-
- u32 new_size = alloc->last_alloc_size + extra;
- return vg_linear_resize( buffer, data, new_size );
-}
-
-/* get the current usage of allocator */
-VG_STATIC u32 vg_linear_get_cur( void *buffer )
-{
- vg_linear_allocator *alloc = vg_linear_header( buffer );
- return alloc->cur;
-}
-
-/* get the capacity of allocator. */
-VG_STATIC u32 vg_linear_get_capacity( void *buffer )
-{
- vg_linear_allocator *alloc = vg_linear_header( buffer );
- return alloc->size;
-}
-
-/* get the remaining size of the allocator */
-VG_STATIC u32 vg_linear_remaining( void *buffer )
-{
- vg_linear_allocator *alloc = vg_linear_header( buffer );
- return alloc->size - alloc->cur;
-}
-
-/* yeet all memory from linear allocator */
-VG_STATIC void vg_linear_clear( void *buffer )
-{
- vg_linear_allocator *alloc = vg_linear_header( buffer );
-
- /* libc mode we recursively free any allocations made */
- if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) )
- {
- for( u32 i=0; i<alloc->allocation_count; i++ )
- {
- vg_allocation_meta *meta = &alloc->alloc_table[i];
-
- if( meta->type == k_allocation_type_block )
- {
- free( meta->data );
- }
- else
- {
- vg_linear_clear( meta->data );
- vg_linear_allocator *sub = vg_linear_header( meta->data );
-
- free( sub->alloc_table );
- free( sub );
- }
- }
- }
-
- alloc->last_alloc = NULL;
- alloc->last_alloc_size = 0;
- alloc->allocation_count = 0;
- alloc->cur = 0;
-}
-
-/* allocate a FIXED SIZE linear allocator */
-VG_STATIC void *vg_create_linear_allocator( void *lin_alloc, u32 size,
- u16 flags )
-{
- assert( sizeof( vg_linear_allocator ) == 32 );
-
- vg_linear_allocator *header;
- u32 block_size = size + sizeof(vg_linear_allocator);
-
- /* Creating it inside an existing one */
- if( lin_alloc )
- {
- vg_linear_allocator *alloc = vg_linear_header( lin_alloc );
-
- if( alloc->cur + block_size > alloc->size )
- vg_fatal_exit_loop( "Out of memory" );
-
- if( alloc->allocation_count + 1 > VG_MAX_ALLOCATIONS )
- vg_fatal_exit_loop( "Max allocations in linear allocator" );
-
- if( (flags && VG_MEMORY_SYSTEM) && (alloc->flags & VG_MEMORY_REALTIME) )
- vg_fatal_exit_loop( "Cannot declare realtime allocator inside systems"
- " allocator" );
-
- if( vg_mem.use_libc_malloc )
- {
- vg_allocation_meta *meta =
- &alloc->alloc_table[ alloc->allocation_count ];
-
- if( flags & VG_MEMORY_REALTIME )
- header = malloc( block_size );
- else
- header = malloc( sizeof(vg_linear_allocator) );
-
- meta->data = header+1;
- meta->type = k_allocation_type_linear;
- }
- else
- {
- header = lin_alloc + alloc->cur;
- }
-
- alloc->cur += block_size;
- alloc->last_alloc = NULL; /* cant resize this block! */
- alloc->last_alloc_size = block_size;
-
- alloc->allocation_count ++;
- }
- else
- {
- if( vg_mem.use_libc_malloc && (flags & VG_MEMORY_SYSTEM) )
- header = malloc( sizeof(vg_linear_allocator) );
- else
- header = malloc( block_size );
- }
-
- header->allocation_count = 0;
- header->cur = 0;
- header->last_alloc = NULL;
- header->last_alloc_size = 0;
- header->size = size;
- header->flags = flags;
-
- if( vg_mem.use_libc_malloc && (flags & VG_MEMORY_SYSTEM) )
- {
- u32 table_size = sizeof(vg_allocation_meta)*VG_MAX_ALLOCATIONS;
- header->alloc_table = malloc( table_size );
- }
- else
- header->alloc_table = NULL;
-
- return header+1;
-}
-
-/* request all the memory we need in advance */
-VG_STATIC void vg_set_mem_quota( u32 size )
-{
- vg_mem.quota = size;
-}
-
-VG_STATIC void vg_alloc_quota(void)
-{
- u32 size_scratch = 10*1024*1024;
- u32 size = VG_MAX( vg_mem.quota, size_scratch );
-
- vg_mem.rtmemory = vg_create_linear_allocator( NULL, size, VG_MEMORY_SYSTEM );
- vg_mem.scratch = vg_create_linear_allocator( vg_mem.rtmemory,
- size_scratch,
- VG_MEMORY_SYSTEM );
-}
-
-#endif /* VG_MEM_H */