Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[6model/c] initial refcount memory manager with tests
- Loading branch information
Showing
8 changed files
with
688 additions
and
11 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,81 @@ | |||
/* mem.h */ | |||
|
|||
/* For initial testing while the harder bits are still incomplete, */ | |||
/* uncomment the following #define. It makes the code the simplest */ | |||
/* thing that could possibly work, but it leaks reference cycles. */ | |||
|
|||
#define REFCOUNT_ONLY 1 /* Warning - commenting out now causes errors */ | |||
|
|||
|
|||
/* mem_block */ | |||
struct mem_block { | |||
/* The size field has special meanings for certain values: */ | |||
/* 0 to INT_MAX: size in bytes, any scalar opaque data (like malloc) */ | |||
/* -1: scalar pointer (reference) to another object */ | |||
/* -2: list of pointers (references) to other objects */ | |||
int size; | |||
struct mem_node * node; | |||
#if defined(REFCOUNT_ONLY) | |||
struct mem_rootdata * rootdata; | |||
int refcount; | |||
#else | |||
struct mem_node * rootnode; | |||
struct mem_node * referrers; | |||
struct mem_node * ref_next; | |||
int level; /* number of hops from root */ | |||
#endif | |||
}; | |||
|
|||
|
|||
/* mem_node */ | |||
/* Connectivity information about each memory object. */ | |||
struct mem_node { | |||
struct mem_block * block; | |||
struct mem_node * rootnode; | |||
struct mem_node * referrers; | |||
struct mem_node * ref_next; | |||
#if ! defined(REFCOUNT_ONLY) | |||
int level; /* number of hops from root */ | |||
#endif | |||
}; | |||
|
|||
|
|||
/* mem_listblock */ | |||
/* Stationary base for list contents */ | |||
struct mem_listblock { | |||
int listsize; | |||
void ** list; | |||
}; | |||
|
|||
|
|||
/* mem_rootdata */ | |||
struct mem_rootdata { | |||
#if defined(REFCOUNT_ONLY) | |||
struct mem_block * blocknext; | |||
struct mem_block * blockprev; | |||
#else | |||
struct mem_node * first; | |||
struct mem_node * last; | |||
#endif | |||
int totalobjects; | |||
long totalbytes; | |||
}; | |||
|
|||
|
|||
/* Function declarations (same whether REFCOUNT_ONLY defined or not) */ | |||
void mem_refdel(void * referrer, void * allocation); | |||
|
|||
void * mem_init(); | |||
void mem_final(void * root, int freeflag); | |||
void * mem_scalar_new(void * parent, int size); | |||
void * mem_scalar_resize(void * object, int newsize); | |||
void mem_scalar_set_ref(void * object, void * target); | |||
void * mem_scalar_get_ref(void * object); | |||
void * mem_list_new(void * parent); | |||
void mem_list_put(void * list, int item, void * target); | |||
void * mem_list_get(void * list, int item); | |||
int mem_size(void * object); | |||
long mem_bytes(void * root); | |||
int mem_objects(void * root); | |||
|
|||
/* end of mem.h */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,104 @@ | |||
/* 02c-mem.t.c */ | |||
/* Test memory management, check for memory leaks in blocks and lists */ | |||
|
|||
#include <stdio.h> /* printf */ | |||
#include <string.h> /* strcpy strlen */ | |||
#include "../../src/mem.h" | |||
#include "../Test.h" /* is_ii i_ll ok plan */ | |||
|
|||
#define TESTOBJECTCOUNT 10000 | |||
#define LINEBUFFERSIZE 128 | |||
|
|||
|
|||
/* test1_7scalars */ | |||
/* Creates many strings, resizes them all, then deletes them. */ | |||
void | |||
test1_7scalars() | |||
{ | |||
int i, totalblocks = 0; | |||
long totalbytes = 0L; | |||
void * rootblock; | |||
void ** testobjects; | |||
char line[LINEBUFFERSIZE]; | |||
|
|||
rootblock = mem_init(); | |||
ok(rootblock!=NULL, "create root node"); /* test 1 */ | |||
|
|||
testobjects = mem_scalar_new(rootblock, TESTOBJECTCOUNT * sizeof(void *)); | |||
totalbytes += TESTOBJECTCOUNT * sizeof(void *); | |||
totalblocks++; | |||
sprintf(line, "allocated array for %d test scalars", TESTOBJECTCOUNT); | |||
ok(testobjects!=NULL, line); /* test 2 */ | |||
|
|||
/* Create TESTOBJECTCOUNT objects on the heap */ | |||
for (i=0; i<TESTOBJECTCOUNT; ++i) { | |||
testobjects[i] = mem_scalar_new(rootblock, 100+i); | |||
totalbytes += 100+i; | |||
totalblocks++; | |||
} | |||
sprintf(line, "%d total scalar blocks", totalblocks); | |||
is_ii(mem_objects(rootblock), totalblocks, line); /* test 3 */ | |||
sprintf(line, "%ld total scalar bytes", totalbytes); | |||
is_ll(mem_bytes(rootblock), totalbytes, line); /* test 4 */ | |||
|
|||
/* Resize the even numbered objects up and the odd ones down */ | |||
for (i=0; i<TESTOBJECTCOUNT; ++i) { | |||
testobjects[i] = mem_scalar_resize(testobjects[i], 20+2*i ); | |||
totalbytes += -(100+i) + (20+2*i); | |||
} | |||
sprintf(line, "after reallocation %ld total bytes", totalbytes); | |||
is_ll(mem_bytes(rootblock), totalbytes, line); /* test 5 */ | |||
|
|||
/* Unreference all the objects that were created on the heap */ | |||
/* This is how you "free" memory allocations */ | |||
for (i=0; i<TESTOBJECTCOUNT; ++i) { | |||
mem_refdel(rootblock, testobjects[i]); | |||
totalbytes -= (20+2*i); | |||
totalblocks--; | |||
} | |||
sprintf(line, "release array leaves %ld total bytes", totalbytes); | |||
is_ll(mem_bytes(rootblock), totalbytes, line); /* test 6 */ | |||
sprintf(line, "release array leaves %d total nodes", totalblocks); | |||
is_ii(mem_objects(rootblock), totalblocks, line); /* test 7 */ | |||
|
|||
/* Release the array containing the test objects */ | |||
mem_refdel(rootblock, testobjects); | |||
|
|||
mem_final(rootblock, 1); | |||
} | |||
|
|||
|
|||
/* test8_9lists */ | |||
/* Create and use a list containing two integers and two strings. */ | |||
void | |||
test8_9lists_of_lists() | |||
{ | |||
void * root, * list0, * list1, * scalar0, * scalar1; | |||
char * answer = "forty-two"; | |||
root = mem_init(); | |||
scalar0 = mem_scalar_new(root, sizeof(int)); | |||
* (int *) scalar0 = 42; | |||
scalar1 = mem_scalar_new(root, strlen(answer)+1); | |||
strcpy(scalar1, answer); | |||
list0 = mem_list_new(root); | |||
mem_list_put(list0, 0, scalar0); | |||
mem_list_put(list0, 1, scalar1); | |||
is_ii(* (int *) mem_list_get(list0, 0), 42, "list0[0] is 42" ); | |||
is_ss((char *) mem_list_get(list0, 1), answer, "list0[1] is \"forty-two\"" ); | |||
/* Unreference the memory to let garbage collection recycle it. */ | |||
mem_refdel(root, list0); | |||
mem_final(root, 1); | |||
} | |||
|
|||
|
|||
/* main */ | |||
int | |||
main(int argc, char * argv[]) | |||
{ | |||
plan(9); | |||
test1_7scalars(); | |||
test8_9lists_of_lists(); | |||
return 0; /* aftwerwards Valgrind should find no memory leaks */ | |||
} | |||
|
|||
/* end of 02c-mem.t.c */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters