2006-02-06 22:25:02 +08:00
|
|
|
/** \file halloc.c
|
2006-02-07 02:11:01 +08:00
|
|
|
|
|
|
|
A hierarchical memory allocation system. Works just like talloc
|
|
|
|
used in Samba, except that an arbitrary block allocated with
|
|
|
|
malloc() can be registered to be freed by halloc_free.
|
|
|
|
|
2006-02-06 22:25:02 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include "util.h"
|
|
|
|
#include "common.h"
|
|
|
|
#include "halloc.h"
|
|
|
|
|
|
|
|
typedef struct halloc
|
|
|
|
{
|
|
|
|
array_list_t children;
|
|
|
|
long long data[0];
|
|
|
|
}
|
|
|
|
halloc_t;
|
|
|
|
|
|
|
|
static halloc_t *halloc_from_data( void *data )
|
|
|
|
{
|
|
|
|
return (halloc_t *)(data - sizeof( halloc_t ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void *halloc( void *context, size_t size )
|
2006-02-09 23:50:20 +08:00
|
|
|
{
|
2006-02-07 02:11:01 +08:00
|
|
|
halloc_t *me, *parent;
|
2006-02-06 22:25:02 +08:00
|
|
|
|
2006-02-07 02:11:01 +08:00
|
|
|
me = (halloc_t *)calloc( 1, sizeof(halloc_t) + size );
|
2006-02-09 23:50:20 +08:00
|
|
|
|
2006-02-07 02:11:01 +08:00
|
|
|
if( !me )
|
|
|
|
return 0;
|
2006-02-09 23:50:20 +08:00
|
|
|
|
2006-02-07 02:11:01 +08:00
|
|
|
al_init( &me->children );
|
2006-02-09 23:50:20 +08:00
|
|
|
|
2006-02-06 22:25:02 +08:00
|
|
|
if( context )
|
2006-02-07 02:11:01 +08:00
|
|
|
{
|
|
|
|
parent = halloc_from_data( context );
|
2006-02-09 23:50:20 +08:00
|
|
|
al_push( &parent->children, &halloc_free );
|
|
|
|
al_push( &parent->children, &me->data );
|
2006-02-06 22:25:02 +08:00
|
|
|
}
|
2006-02-09 23:50:20 +08:00
|
|
|
|
2006-02-07 02:11:01 +08:00
|
|
|
return &me->data;
|
2006-02-06 22:25:02 +08:00
|
|
|
}
|
|
|
|
|
2006-02-09 23:50:20 +08:00
|
|
|
void halloc_register_function( void *context, void (*func)(void *), void *data )
|
2006-02-06 22:25:02 +08:00
|
|
|
{
|
|
|
|
halloc_t *me;
|
|
|
|
if( !context )
|
2006-02-09 23:50:20 +08:00
|
|
|
return;
|
2006-02-06 22:25:02 +08:00
|
|
|
|
|
|
|
me = halloc_from_data( context );
|
2006-02-09 23:50:20 +08:00
|
|
|
al_push( &me->children, func );
|
2006-02-07 02:11:01 +08:00
|
|
|
al_push( &me->children, data );
|
2006-02-06 22:25:02 +08:00
|
|
|
}
|
|
|
|
|
2006-02-07 02:11:01 +08:00
|
|
|
void halloc_free( void *context )
|
2006-02-06 22:25:02 +08:00
|
|
|
{
|
2006-02-07 02:11:01 +08:00
|
|
|
halloc_t *me;
|
2006-02-09 23:50:20 +08:00
|
|
|
int i;
|
|
|
|
|
2006-02-07 02:11:01 +08:00
|
|
|
if( !context )
|
|
|
|
return;
|
2006-02-09 23:50:20 +08:00
|
|
|
|
2006-02-07 02:11:01 +08:00
|
|
|
me = halloc_from_data( context );
|
2006-02-09 23:50:20 +08:00
|
|
|
for( i=0; i<al_get_count(&me->children); i+=2 )
|
|
|
|
{
|
|
|
|
void (*func)(void *) = (void (*)(void *))al_get( &me->children, i );
|
|
|
|
void * data = (void *)al_get( &me->children, i+1 );
|
|
|
|
func( data );
|
|
|
|
}
|
2006-02-07 02:11:01 +08:00
|
|
|
al_destroy( &me->children );
|
|
|
|
free(me);
|
2006-02-06 22:25:02 +08:00
|
|
|
}
|