<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="default.xsl"?>
<fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="true"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>343</fr:anchor><fr:addr
type="user">ocs-0004</fr:addr><fr:route>ocs-0004.xml</fr:route><fr:title
text="Notes › Arena Allocator › Logic behind the allocator"><fr:link
type="local"
href="ocs-0003.xml"
addr="ocs-0003"
title="Notes › Arena Allocator"><fr:link
type="local"
href="ocs-0002.xml"
addr="ocs-0002"
title="Notes">Notes</fr:link> › Arena Allocator</fr:link> › Logic behind the allocator</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:p>Only requires an offset or pointer to state the end of the last allocation. To allocate some memory from the arena it is as simple as moving the offset (or pointer) forward. The allocation has the complexity of <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>.

 Due to being the simplest allocator possible, the arena allocator does nto allow the user to free certain blocks of memory. The memory is usually <fr:em>freed all at once</fr:em>.</fr:p></fr:mainmatter><fr:backmatter><fr:tree
toc="false"
numbered="false"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:title
text="Context">Context</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:tree
toc="true"
numbered="false"
show-heading="true"
show-metadata="true"
expanded="false"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>344</fr:anchor><fr:addr
type="user">ocs-0003</fr:addr><fr:route>ocs-0003.xml</fr:route><fr:title
text="Notes › Arena Allocator"><fr:link
type="local"
href="ocs-0002.xml"
addr="ocs-0002"
title="Notes">Notes</fr:link> › Arena Allocator</fr:title><fr:taxon>Note</fr:taxon><fr:date><fr:year>2024</fr:year><fr:month>5</fr:month><fr:day>29</fr:day></fr:date><fr:authors /></fr:frontmatter><fr:mainmatter><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>251</fr:anchor><fr:addr
type="user">ocs-0004</fr:addr><fr:route>ocs-0004.xml</fr:route><fr:title
text="Logic behind the allocator">Logic behind the allocator</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:p>Only requires an offset or pointer to state the end of the last allocation. To allocate some memory from the arena it is as simple as moving the offset (or pointer) forward. The allocation has the complexity of <fr:tex
display="inline"><![CDATA[O(1)]]></fr:tex>.

 Due to being the simplest allocator possible, the arena allocator does nto allow the user to free certain blocks of memory. The memory is usually <fr:em>freed all at once</fr:em>.</fr:p></fr:mainmatter><fr:backmatter /></fr:tree><fr:tree
toc="true"
numbered="true"
show-heading="true"
show-metadata="false"
expanded="true"
root="false"
xmlns:fr="http://www.jonmsterling.com/jms-005P.xml"><fr:frontmatter><fr:anchor>252</fr:anchor><fr:addr
type="user">ocs-0005</fr:addr><fr:route>ocs-0005.xml</fr:route><fr:title
text="Basic arena interface">Basic arena interface</fr:title><fr:authors /></fr:frontmatter><fr:mainmatter><fr:p>An arena is like a stack with extensions, e.g. it can be named.</fr:p><fr:pre><![CDATA[Arena *arena_alloc(void);
void arena_release(Arena *arena);
void arena_set_auto_align(Arena *arena, u64 align);

u64 arena_pos(Arena *arena);

void *arena_push_no_zero(Arena *arena, u64 size);
void *arena_push_aligner(Arena *arena, u64 alignment);
void *arena_push(Arena *arena, u64 size);

void arena_pop_to(Arena *arena, u64 pos);
void arena_pop(Arena *arena, u64 size);
void arena_clear(Arena *arena);

#define PushArrayNoZero(arena, type, count) (type *) \
    arena_push_no_zero((arena), sizeof(type) * (count))
#define PushArray(arena, type, count) (type *) \
    arena_push((arena), sizeof(type) * (count))]]></fr:pre><fr:p>the simplest arena allocator will look something like</fr:p><fr:pre><![CDATA[static unsigned char *arena_buffer;
static size_t arena_buffer_length;
static size_t arena_offset;

void *arena_alloc(size_t size) {
    // Check to see if the backing memory has space left
    if (arena_offset+size <= arena_buffer_length) {
        void *ptr = &arena_buffer[arena_offset];
        arena_offset += size;

        // Zero memory
        memset(ptr, 0, size);
        return ptr;
    }
    return NULL;
}]]></fr:pre><fr:p>While this is as simple as it gets, there are two issues with the basic approach
  * You cannot reuse this procedure for different arenas.
  * The pointer returned may not be aligned correctly for the data you need.

 The first issue can be solved by coupling the data into a structure and passing that to the procedure =arena_alloc=.</fr:p></fr:mainmatter><fr:backmatter /></fr:tree></fr:mainmatter><fr:backmatter /></fr:tree></fr:mainmatter><fr:backmatter /></fr:tree></fr:backmatter></fr:tree>