Permalink
Browse files

arena.c: make Arena_alloc use existing chunk if there's one that has …

…enough space (exercise 6.1/p100)
  • Loading branch information...
1 parent 7428f4d commit 3b8ab175205738b4ef77062e1c5391514b4a7c74 @thaidn committed Apr 20, 2012
Showing with 36 additions and 3 deletions.
  1. +1 −0 include/arena.h
  2. +35 −3 src/arena.c
View
@@ -13,5 +13,6 @@ extern void *Arena_alloc (T arena, long nbytes,
extern void *Arena_calloc(T arena, long count,
long nbytes, const char *file, int line);
extern void Arena_free (T arena);
+extern int Arena_count(T arena);
#undef T
#endif
View
@@ -1,15 +1,17 @@
-static char rcsid[] = "$Id: arena.c 6 2007-01-22 00:45:22Z drhanson $";
#include <stdlib.h>
#include <string.h>
#include "assert.h"
#include "except.h"
#include "arena.h"
+
#define T Arena_T
+#define THRESHOLD 10
+
const Except_T Arena_NewFailed =
- { "Arena Creation Failed" };
+ { "Arena Creation Failed" };
const Except_T Arena_Failed =
{ "Arena Allocation Failed" };
-#define THRESHOLD 10
+
struct T {
T prev;
char *avail;
@@ -35,29 +37,45 @@ union header {
};
static T freechunks;
static int nfree;
+
T Arena_new(void) {
T arena = malloc(sizeof (*arena));
+
if (arena == NULL)
RAISE(Arena_NewFailed);
arena->prev = NULL;
arena->limit = arena->avail = NULL;
return arena;
}
+
void Arena_dispose(T *ap) {
assert(ap && *ap);
Arena_free(*ap);
free(*ap);
*ap = NULL;
}
+
void *Arena_alloc(T arena, long nbytes,
const char *file, int line) {
+ T tmp;
+
assert(arena);
assert(nbytes > 0);
nbytes = ((nbytes + sizeof (union align) - 1)/
(sizeof (union align)))*(sizeof (union align));
+ tmp = arena;
+ while (tmp->prev) {
+ if (nbytes > tmp->limit - tmp->avail) {
+ tmp = tmp->prev;
+ } else {
+ arena = tmp;
+ break;
+ }
+ }
while (nbytes > arena->limit - arena->avail) {
T ptr;
char *limit;
+
if ((ptr = freechunks) != NULL) {
freechunks = freechunks->prev;
nfree--;
@@ -82,14 +100,17 @@ void *Arena_alloc(T arena, long nbytes,
arena->avail += nbytes;
return arena->avail - nbytes;
}
+
void *Arena_calloc(T arena, long count, long nbytes,
const char *file, int line) {
void *ptr;
+
assert(count > 0);
ptr = Arena_alloc(arena, count*nbytes, file, line);
memset(ptr, '\0', count*nbytes);
return ptr;
}
+
void Arena_free(T arena) {
assert(arena);
while (arena->prev) {
@@ -106,3 +127,14 @@ void Arena_free(T arena) {
assert(arena->limit == NULL);
assert(arena->avail == NULL);
}
+
+int Arena_count(T arena) {
+ int i = 0;
+
+ assert(arena);
+ while (arena->prev) {
+ ++i;
+ arena = arena->prev;
+ }
+ return i;
+}

0 comments on commit 3b8ab17

Please sign in to comment.