diff --git a/Source/charon/allocator.c b/Source/charon/allocator.c index ca63f6956..bf35ad630 100644 --- a/Source/charon/allocator.c +++ b/Source/charon/allocator.c @@ -28,6 +28,10 @@ #include #include +#ifndef ALLOCATOR_C_ +#define ALLOCATOR_C_ +#endif + #include "allocator.h" #ifdef LEAK_DETECTIVE @@ -45,22 +49,38 @@ union memory_hdr_u { }; /** - * global list of allocations - * - * thread-save through mutex + * private allocator_t object */ -static memory_hdr_t *allocations = NULL; +typedef struct private_allocator_s private_allocator_t; + +struct private_allocator_s +{ + /** + * public part of an allocator_t object + */ + allocator_t public; + + /** + * global list of allocations + * + * thread-save through mutex + */ + memory_hdr_t *allocations; + + /** + * Mutex to ensure, all functions are thread-save + */ + pthread_mutex_t mutex; + +}; + /** - * Mutex to ensure, all functions are thread-save + * implements allocator_t's function allocate */ -static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; - -/* - * described in header - */ -void * allocate(size_t bytes, char * file,int line) +static void * allocate(allocator_t *allocator,size_t bytes, char * file,int line) { + private_allocator_t *this = (private_allocator_t *) allocator; memory_hdr_t *allocated_memory = malloc(sizeof(memory_hdr_t) + bytes); if (allocated_memory == NULL) @@ -68,38 +88,39 @@ void * allocate(size_t bytes, char * file,int line) return allocated_memory; } - pthread_mutex_lock( &mutex); + pthread_mutex_lock( &(this->mutex)); allocated_memory->info.line = line; allocated_memory->info.filename = file; allocated_memory->info.size_of_memory = bytes; - allocated_memory->info.older = allocations; - if (allocations != NULL) + allocated_memory->info.older = this->allocations; + if (this->allocations != NULL) { - allocations->info.newer = allocated_memory; + this->allocations->info.newer = allocated_memory; } - allocations = allocated_memory; + this->allocations = allocated_memory; allocated_memory->info.newer = NULL; /* fill memory with zero's */ memset(allocated_memory+1, '\0', bytes); - pthread_mutex_unlock( &mutex); + pthread_mutex_unlock(&(this->mutex)); /* real memory starts after header */ return (allocated_memory+1); } -/* - * described in header - */ -void free_pointer(void * pointer) +/** + * implements allocator_t's function free_pointer + */ +static void free_pointer(allocator_t *allocator, void * pointer) { + private_allocator_t *this = (private_allocator_t *) allocator; memory_hdr_t *allocated_memory; if (pointer == NULL) { return; } - pthread_mutex_lock( &mutex); + pthread_mutex_lock( &(this->mutex)); allocated_memory = ((memory_hdr_t *)pointer) - 1; if (allocated_memory->info.older != NULL) @@ -109,56 +130,58 @@ void free_pointer(void * pointer) } if (allocated_memory->info.newer == NULL) { - assert(allocated_memory == allocations); - allocations = allocated_memory->info.older; + assert(allocated_memory == this->allocations); + this->allocations = allocated_memory->info.older; } else { assert(allocated_memory->info.newer->info.older == allocated_memory); allocated_memory->info.newer->info.older = allocated_memory->info.older; } - pthread_mutex_unlock( &mutex); + pthread_mutex_unlock(&(this->mutex)); free(allocated_memory); } -/* - * described in header - */ -void * reallocate(void * old, size_t bytes, char * file,int line) +/** + * implements allocator_t's function reallocate + */ +static void * reallocate(allocator_t *allocator, void * old, size_t bytes, char * file,int line) { + private_allocator_t *this = (private_allocator_t *) allocator; memory_hdr_t *allocated_memory; if (old == NULL) { return NULL; } - pthread_mutex_lock( &mutex); + pthread_mutex_lock( &(this->mutex)); allocated_memory = ((memory_hdr_t *)old) - 1; - void *new_space = allocate(bytes,file,line); + void *new_space = this->public.allocate(&(this->public),bytes,file,line); if (new_space == NULL) { - free_pointer(old); - pthread_mutex_unlock( &mutex); + this->public.free_pointer(&(this->public),old); + pthread_mutex_unlock(&(this->mutex)); return NULL; } memcpy(new_space,old,allocated_memory->info.size_of_memory); - pthread_mutex_unlock( &mutex); + pthread_mutex_unlock(&(this->mutex)); return new_space; } - -/* - * described in header - */ -void report_memory_leaks(void) +/** + * implements allocator_t's function report_memory_leaks + */ +static void allocator_report_memory_leaks(allocator_t *allocator) { - memory_hdr_t *p = allocations, - *pprev = NULL; + private_allocator_t *this = (private_allocator_t *) allocator; + memory_hdr_t *p = this->allocations; + memory_hdr_t *pprev = NULL; unsigned long n = 0; - pthread_mutex_lock( &mutex); + + pthread_mutex_lock(&(this->mutex)); while (p != NULL) { @@ -169,13 +192,26 @@ void report_memory_leaks(void) if (p == NULL || pprev->info.filename != p->info.filename) { if (n != 1) - fprintf(stderr,"leak: %lu * File %s, Line %d\n", n, pprev->info.filename,pprev->info.line); + fprintf(stderr,"LEAK: \"%lu * File %s, Line %d\"\n", n, pprev->info.filename,pprev->info.line); else - fprintf(stderr,"leak: File %s, Line %d\n", pprev->info.filename,pprev->info.line); + fprintf(stderr,"LEAK: \"%s, Line %d\"\n", pprev->info.filename,pprev->info.line); n = 0; } } - pthread_mutex_unlock( &mutex); + pthread_mutex_unlock( &(this->mutex)); } +static private_allocator_t allocator = { + public: {allocate: allocate, + free_pointer: free_pointer, + reallocate: reallocate, + report_memory_leaks: allocator_report_memory_leaks}, + allocations: NULL, + mutex: PTHREAD_MUTEX_INITIALIZER +}; + +//allocator.public.allocate = (void *) (allocator_t *,size_t, char *,int) allocate; + + +allocator_t *global_allocator = &(allocator.public); #endif diff --git a/Source/charon/allocator.h b/Source/charon/allocator.h index 9c74ada0d..bd719f206 100644 --- a/Source/charon/allocator.h +++ b/Source/charon/allocator.h @@ -35,56 +35,76 @@ #define allocator_alloc_thing(thing) (allocator_alloc(sizeof(thing))) #ifdef LEAK_DETECTIVE - /** - * Allocates memory with LEAK_DETECTION and - * returns an empty data area filled with zeros - * - * @warning use this function not directly, only with assigned macros - * allocator_alloc and allocator_alloc_thing - * - * @param bytes number of bytes to allocate - * @param file filename from which the memory is allocated - * @param line line number in specific file - * @return allocated memory area - */ - void * allocate(size_t bytes, char * file,int line); - /** - * Reallocates memory with LEAK_DETECTION and - * returns an empty data area filled with zeros - * - * @warning use this function not directly, only with assigned macro - * allocator_realloc - * - * @param old pointer to the old data area - * @param bytes number of bytes to allocate - * @param file filename from which the memory is allocated - * @param line line number in specific file - * @return reallocated memory area - */ - void * reallocate(void * old, size_t bytes, char * file, int line); - /** - * Frees memory with LEAK_DETECTION - * - * @warning use this function not directly, only with assigned macro - * allocator_free - * - * @param pointer pointer to the data area to free - */ - void free_pointer(void * pointer); + typedef struct allocator_s allocator_t; + + struct allocator_s { + + /** + * Allocates memory with LEAK_DETECTION and + * returns an empty data area filled with zeros + * + * @warning use this function not directly, only with assigned macros + * allocator_alloc and allocator_alloc_thing + * + * @param this allocator_t object + * @param bytes number of bytes to allocate + * @param file filename from which the memory is allocated + * @param line line number in specific file + * @return allocated memory area + */ + void * (*allocate) (allocator_t *this,size_t bytes, char * file,int line); + + /** + * Reallocates memory with LEAK_DETECTION and + * returns an empty data area filled with zeros + * + * @warning use this function not directly, only with assigned macro + * allocator_realloc + * + * @param this allocator_t object + * @param old pointer to the old data area + * @param bytes number of bytes to allocate + * @param file filename from which the memory is allocated + * @param line line number in specific file + * @return reallocated memory area + */ + void * (*reallocate) (allocator_t *this,void * old, size_t bytes, char * file, int line); + /** + * Frees memory with LEAK_DETECTION + * + * @warning use this function not directly, only with assigned macro + * allocator_free + * + * @param this allocator_t object + * @param pointer pointer to the data area to free + */ + void (*free_pointer) (allocator_t *this,void * pointer); + + /** + * Report memory leaks to stderr + * + * @warning use this function not directly, only with assigned macro + * report_memory_leaks + * + * @param this allocator_t object + */ + void (*report_memory_leaks) (allocator_t *this); + }; - #define allocator_alloc(bytes) (allocate(bytes,__FILE__,__LINE__)) - #define allocator_realloc(old,bytes) (reallocate(old,bytes,__FILE__, __LINE__)) - #define allocator_free(pointer) (free_pointer(pointer)) + #ifndef ALLOCATOR_C_ + extern allocator_t *global_allocator; + #endif + + #define allocator_alloc(bytes) (global_allocator->allocate(global_allocator,bytes,__FILE__,__LINE__)) + #define allocator_realloc(old,bytes) (global_allocator->reallocate(global_allocator,old,bytes,__FILE__, __LINE__)) + #define allocator_free(pointer) (global_allocator->free_pointer(global_allocator,pointer)) #define allocator_free_chunk(chunk){ \ - free_pointer(chunk.ptr); \ + global_allocator->free_pointer(global_allocator,chunk.ptr); \ chunk.ptr = NULL; \ chunk.len = 0; \ } - /** - * Report memory leaks to stderr - */ - void report_memory_leaks(void); + #define report_memory_leaks(void) global_allocator->report_memory_leaks(global_allocator); #else #define allocator_alloc(bytes) (malloc(bytes)) #define allocator_realloc(old,bytes) (realloc(old,bytes))