Browse Source
Add arena headers
Add arena headers
An arena is a data structure that makes memory management a fair bit simpler. This is an arena type that doesn't do anything fancy; it simply maintains a linked list of blocks from which it doles out memory. It's probably not even that efficient! Future directions for this work include adding more options and implementation details: * custom allocators * object destructors * strcpy instead of just strncpy support * large-block allocation support * block data structure that is more concurrency safetrunk
2 changed files with 135 additions and 0 deletions
-
121src/arena.c
-
14src/arena.h
@ -0,0 +1,121 @@ |
|||||
|
#include <stdlib.h> |
||||
|
#include <strings.h> |
||||
|
|
||||
|
#include "arena.h" |
||||
|
|
||||
|
struct arena_block { |
||||
|
struct arena_block *next; |
||||
|
size_t used; |
||||
|
char data[]; |
||||
|
}; |
||||
|
|
||||
|
struct arena { |
||||
|
size_t block_size; /* size of blocks to allocate */ |
||||
|
struct arena_block *head, *last; |
||||
|
}; |
||||
|
|
||||
|
struct arena *arena_create(size_t block_size) { |
||||
|
// allocate an initial block |
||||
|
struct arena * result = (struct arena *) malloc(sizeof(struct arena) + sizeof(struct arena_block) + block_size); |
||||
|
if (result == NULL) { |
||||
|
return NULL; |
||||
|
} |
||||
|
result->block_size = block_size; |
||||
|
result->head = (struct arena_block *) (result + 1); |
||||
|
result->head->next = NULL; |
||||
|
result->head->used = 0; |
||||
|
result->last = result->head; |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
void arena_destroy(struct arena *arena) { |
||||
|
if (arena == NULL) { |
||||
|
return; // error? |
||||
|
} |
||||
|
struct arena_block *blk = arena->head->next; |
||||
|
while (blk != NULL) { |
||||
|
struct arena_block *tmp = blk->next; |
||||
|
free(blk); |
||||
|
blk = tmp; |
||||
|
}; |
||||
|
free(arena); |
||||
|
} |
||||
|
|
||||
|
void *arena_malloc(struct arena *arena, size_t size) { |
||||
|
struct arena_block *block; |
||||
|
if (size > arena->block_size) { |
||||
|
return NULL; |
||||
|
} else if (size < arena->block_size - arena->last->used) { |
||||
|
block = arena->last; |
||||
|
} else { |
||||
|
block = (struct arena_block *) malloc(sizeof(struct arena_block) + arena->block_size); |
||||
|
if (block == NULL) { |
||||
|
return NULL; |
||||
|
} |
||||
|
block->next = NULL; |
||||
|
block->used = 0; |
||||
|
arena->last->next = block; |
||||
|
arena->last = block; |
||||
|
} |
||||
|
void *ret = block->data + block->used; |
||||
|
block->used += size; |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
void *arena_calloc(struct arena *arena, size_t count, size_t size) { |
||||
|
return arena_malloc(arena, count * size); |
||||
|
} |
||||
|
|
||||
|
void *arena_copy_alloc(struct arena *arena, const void *src, size_t len) { |
||||
|
void *dst = arena_malloc(arena, len); |
||||
|
if (dst == NULL) { |
||||
|
return NULL; |
||||
|
} |
||||
|
return memcpy(dst, src, len); |
||||
|
} |
||||
|
|
||||
|
void *arena_strcpy_alloc(struct arena *arena, const void *src, size_t len) { |
||||
|
if (arena == NULL) { |
||||
|
return NULL; |
||||
|
} |
||||
|
size_t true_len = strnlen(src, len) + 1; |
||||
|
void *dst = arena_malloc(arena, true_len); |
||||
|
if (dst == NULL) { |
||||
|
return NULL; |
||||
|
} |
||||
|
memcpy(dst, src, true_len - 1); |
||||
|
((char *)dst)[true_len - 1] = '\0'; |
||||
|
return dst; |
||||
|
} |
||||
|
|
||||
|
size_t arena_used(struct arena *arena) { |
||||
|
size_t total = 0; |
||||
|
if (arena != NULL) { |
||||
|
for (struct arena_block *block = arena->head; block != NULL; block = block->next) { |
||||
|
total += block->used; |
||||
|
} |
||||
|
} |
||||
|
return total; |
||||
|
} |
||||
|
|
||||
|
size_t arena_overhead(struct arena *arena) { |
||||
|
size_t total = 0; |
||||
|
if (arena != NULL) { |
||||
|
total += sizeof(struct arena); |
||||
|
for (struct arena_block *block = arena->head; block != NULL; block = block->next) { |
||||
|
total += sizeof(struct arena_block); |
||||
|
} |
||||
|
} |
||||
|
return total; |
||||
|
} |
||||
|
|
||||
|
size_t arena_total_capacity(struct arena *arena) { |
||||
|
size_t total = 0; |
||||
|
if (arena != NULL) { |
||||
|
for (struct arena_block *block = arena->head; block != NULL; block = block->next) { |
||||
|
total += arena->block_size; |
||||
|
} |
||||
|
} |
||||
|
return total; |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
|
||||
|
struct arena; |
||||
|
|
||||
|
struct arena *arena_create(size_t block_size); |
||||
|
void arena_destroy(struct arena *); |
||||
|
|
||||
|
void *arena_malloc(struct arena *, size_t size); |
||||
|
void *arena_calloc(struct arena *, size_t count, size_t size); |
||||
|
void *arena_copy_alloc(struct arena *, const void *src, size_t len); |
||||
|
void *arena_strcpy_alloc(struct arena *, const void *src, size_t len); |
||||
|
|
||||
|
size_t arena_used(struct arena *); |
||||
|
size_t arena_overhead(struct arena *); |
||||
|
size_t arena_total_capacity(struct arena *); |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue