111 lines
3.4 KiB
C
111 lines
3.4 KiB
C
/// __ ___ __ ___ _ __ __ _
|
|
/// \ \/ / '__/ _ \ '_ \ / _` |
|
|
/// > <| | | __/ | | | (_| |
|
|
/// /_/\_\_| \___|_| |_|\__,_|
|
|
///
|
|
/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
|
|
///
|
|
/// xolatile@chud.cyou - xrena - Probably the most minimalistic arena allocator possible, and undoubtedly evil in implementation details.
|
|
///
|
|
/// This program is free software, free as in freedom and as in free beer, you can redistribute it and/or modify it under the terms of the GNU
|
|
/// General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version if you wish...
|
|
///
|
|
/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
|
|
/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
|
|
/// for more details, if you dare, it is a lot of text that nobody wants to read...
|
|
|
|
#ifndef arena_block_limit
|
|
#define arena_block_limit (1024 * 1024)
|
|
#endif
|
|
|
|
static struct {
|
|
natural_64 block_count;
|
|
natural_64 block_limit;
|
|
struct {
|
|
natural_64 count;
|
|
natural_64 capacity;
|
|
character * buffer;
|
|
} * * block_array;
|
|
} * arena = null;
|
|
|
|
static procedure arena_initialize (none) {
|
|
natural_64 current = ++arena->block_count - 1;
|
|
|
|
arena->block_limit = arena_block_limit;
|
|
|
|
arena->block_array = reallocate (arena->block_array, arena->block_count * sizeof (* arena->block_array));
|
|
|
|
arena->block_array [current] = allocate (sizeof (* arena));
|
|
|
|
arena->block_array [current]->buffer = allocate (arena_block_limit);
|
|
arena->block_array [current]->count = 0;
|
|
arena->block_array [current]->capacity = arena_block_limit;
|
|
}
|
|
|
|
static procedure arena_deinitialize (none) {
|
|
for (natural_64 index = 0; index < arena->block_count; ++index) {
|
|
arena->block_array [index]->buffer = deallocate (arena->block_array [index]->buffer);
|
|
arena->block_array [index] = deallocate (arena->block_array [index]);
|
|
}
|
|
|
|
arena->block_array = deallocate (arena->block_array);
|
|
arena = deallocate (arena);
|
|
}
|
|
|
|
static generic * arena_add (natural_64 size) {
|
|
natural_64 current = arena->block_count - 1;
|
|
|
|
if (arena == null) {
|
|
clean_up (arena_deinitialize);
|
|
|
|
arena = allocate (sizeof (* arena));
|
|
|
|
arena_initialize ();
|
|
}
|
|
|
|
fatal_failure (size > arena->block_limit, "arena_add: Block limit reached.");
|
|
|
|
if (arena->block_array [current]->count + size > arena->block_array [current]->capacity) {
|
|
arena_initialize ();
|
|
}
|
|
|
|
arena->block_array [current]->count += size;
|
|
|
|
return ((v0*) & arena->block_array [current]->buffer [arena->block_array [current]->count - size]);
|
|
}
|
|
|
|
static character * arena_add_data (generic * data, natural_64 size) {
|
|
generic * pointer = arena_add (size);
|
|
|
|
memory_copy (pointer, data, size);
|
|
|
|
return (pointer);
|
|
}
|
|
|
|
static character * arena_add_file (character * path, natural flag, boolean null_terminate) {
|
|
integer file = -1;
|
|
natural_64 size = 0;
|
|
character * data = null;
|
|
|
|
file = file_open (path, flag);
|
|
size = file_size (path) + (natural_64) null_terminate;
|
|
data = arena_add (size);
|
|
|
|
file_read (file, data, size - (natural_64) null_terminate);
|
|
|
|
file = file_close (file);
|
|
|
|
return (data);
|
|
}
|
|
|
|
static natural_64 arena_usage (none) {
|
|
natural_64 usage = 0;
|
|
|
|
for (natural_64 block = 0; block < arena->block_count; ++block) {
|
|
usage += arena->block_array [block]->count;
|
|
}
|
|
|
|
return (usage);
|
|
}
|
|
|