- allocator functionality capsulated in a global object

This commit is contained in:
Jan Hutter 2005-11-10 07:31:17 +00:00
parent fd1a4d0a6b
commit f5b44696ed
2 changed files with 145 additions and 89 deletions

View File

@ -28,6 +28,10 @@
#include <assert.h>
#include <stdio.h>
#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

View File

@ -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))