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