Browse Source

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 safe
trunk
Shanti Chellaram 5 years ago
parent
commit
7bae84d126
  1. 121
      src/arena.c
  2. 14
      src/arena.h

121
src/arena.c

@ -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;
}

14
src/arena.h

@ -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 *);
Loading…
Cancel
Save