Obstack
20 04 2008
Obstack es otros de los medios que emplea la librería C de GNU para la asignación dinámica de memoria. Obstack es una pila de objetos (datos) que puede crecer dinámicamente. Es posible crear cualquier número de obstacks para, en cada uno, ir almacenando diferentes conjuntos de datos. En cada obstack el último objeto en entrar es el primero en salir.
Obstack es pues otro de los métodos de la librería glibc para la reserva dinámica de memoria.
A parte de esta limitación en el orden de almacenaje obstack es capaz de contener cualquier número de objetos de cualquier tamaño. Obstack está implementado con macros, de manera que la asignación de espacio es muy rápida si los objetos son pequeños. La única sobrecarga por objeto es el relleno necesario para colocar un objeto en unos límites adecuados.
Para la creación de un obstack debes primero incluir el archivo de cabecera obstack.h. En este archivo se declara la estructura obstack de tamaño fijo y que registra el estado del obstack y como encontrar el espacio donde los objetos están localizados. No se debe intentar acceder al contenido de esta estructura directamente sino que se debe utilizar las funciones diseñadas especificamente para obstack.
Obstack puede ser tratado como cualquier otro tipo de objetos, puedes crear obstack dinamicamente o crear obstacks que contengan a su vez otros obstacks.
Todas las funciones que trabajan con obstacks necesitan que se les especifique el obstack a usar. Se hace esto a través de un puntero a la estructura de tipo struct obstack* .
Los objetos dentro del obstack son empaquetados en bloques llamados chunks. La estructura obstack apunta a una cadena de chunks actualmente en uso.
La librería obstack obtiene un nuevo chunk cada vez que debe insertar un nuevo objeto que no cabe en un chunk anterior. La librería administra automáticamente estos chunks de manera que no hay que prestarles demasiada atención, pero hay que propocionar una función a la librería obstack para que esta se haga con un nuevo chunk. Generalmente se debe proporcionar un a función que emplea malloc directa o indirectamente. También se debe proporcionar una función que libere el chunk (free).
Ejemplo:
#include //declara todas las variables, funciones y macros necesarios para obstack
//Estas dos macros definen los métodos para la generación de memoria dinámica y su liberación
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
...
//función que se llamara en el caso de error en la reserva dinámica de memoria
void my_obstack_alloc_failed(void)
{
...
}
...
//Declaramos nuestra estructura obstack
static struct obstack myobstack;
...
//La inicializamos
obstack_init(&myobstack);
...
//Declaramos que función será llamada en caso de error al reservar memoria dinámica
obstack_alloc_failed_handler = &my_obstack_alloc_failed;
//Grabamos en nuestro obstack la cadena "hola mundo"
obstack_alloc("hola mundo",11);
Para almacenar un bloque con un contendio específico utilizamos la función obstack_copy
void* obstack_copy (struct obstack* obstack-ptr, void* address, int size)
La función obstrack_copy0 además agrega un caracter nulo (ascii 0) al final.
void* obstack_copy0 (struct obstack* obstack-ptr, void* address, int size)
En el último argumento size no debemos tener en cuenta este carácter nulo extra. Ejemplo:
char*
obstack_savestring (char* addr, int size)
{
return obstack_copy0 (&myobstack, addr, size);
}
Para liberar objetos en el obstack se emplea obstack_free
void obstack_free (struct obstack* obstack-ptr, void* object)
Si objeto es un puntero nulo, todo lo almacenado en obstack será liberado. Cualquier otro valor debe ser un puntero a un objeto del obstack. Ese objeto será liberado y todos los que se encuentran a continuación de él.
Observa que si object es un puntero nulo, el resultado será un obstack no inicializado. Para liberar todos los objetos del obstack pero dejando el obstack válido para agregar nuevos objetos tenemos que pasarle como object el primer objeto almacenado.
Recuerda que obstack está agrupado en chunks. Si se liberan todos los objetos de un chunk, obstack automaticamente liberará este chunk para que pueda ser utilizado como recurso para otros elementos del programa.
Recordemos que los interfaces definidos en obstack pueden estar definidos como funciones o como macros. Ejemplo:
char* x;
void* (* funcp) ();
/* Use the macro. */
x = (char* ) obstack_alloc (obptr, size);
/* Call the function. */
x = (char* ) (obstack_alloc) (obptr, size);
/* Take the address of the function. */
funcp = obstack_alloc;
Si empleas otro compilador que no sea el de GNU debes tener esto en cuenta.
Para saber más:
GNU C Library Obstacks
Comentarios :
No hay comentarios »
Obstack es pues otro de los métodos de la librería glibc para la reserva dinámica de memoria.
A parte de esta limitación en el orden de almacenaje obstack es capaz de contener cualquier número de objetos de cualquier tamaño. Obstack está implementado con macros, de manera que la asignación de espacio es muy rápida si los objetos son pequeños. La única sobrecarga por objeto es el relleno necesario para colocar un objeto en unos límites adecuados.
Para la creación de un obstack debes primero incluir el archivo de cabecera obstack.h. En este archivo se declara la estructura obstack de tamaño fijo y que registra el estado del obstack y como encontrar el espacio donde los objetos están localizados. No se debe intentar acceder al contenido de esta estructura directamente sino que se debe utilizar las funciones diseñadas especificamente para obstack.
Obstack puede ser tratado como cualquier otro tipo de objetos, puedes crear obstack dinamicamente o crear obstacks que contengan a su vez otros obstacks.
Todas las funciones que trabajan con obstacks necesitan que se les especifique el obstack a usar. Se hace esto a través de un puntero a la estructura de tipo struct obstack* .
Los objetos dentro del obstack son empaquetados en bloques llamados chunks. La estructura obstack apunta a una cadena de chunks actualmente en uso.
La librería obstack obtiene un nuevo chunk cada vez que debe insertar un nuevo objeto que no cabe en un chunk anterior. La librería administra automáticamente estos chunks de manera que no hay que prestarles demasiada atención, pero hay que propocionar una función a la librería obstack para que esta se haga con un nuevo chunk. Generalmente se debe proporcionar un a función que emplea malloc directa o indirectamente. También se debe proporcionar una función que libere el chunk (free).
Ejemplo:
#include
//Estas dos macros definen los métodos para la generación de memoria dinámica y su liberación
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
...
//función que se llamara en el caso de error en la reserva dinámica de memoria
void my_obstack_alloc_failed(void)
{
...
}
...
//Declaramos nuestra estructura obstack
static struct obstack myobstack;
...
//La inicializamos
obstack_init(&myobstack);
...
//Declaramos que función será llamada en caso de error al reservar memoria dinámica
obstack_alloc_failed_handler = &my_obstack_alloc_failed;
//Grabamos en nuestro obstack la cadena "hola mundo"
obstack_alloc("hola mundo",11);
Para almacenar un bloque con un contendio específico utilizamos la función obstack_copy
void* obstack_copy (struct obstack* obstack-ptr, void* address, int size)
La función obstrack_copy0 además agrega un caracter nulo (ascii 0) al final.
void* obstack_copy0 (struct obstack* obstack-ptr, void* address, int size)
En el último argumento size no debemos tener en cuenta este carácter nulo extra. Ejemplo:
char*
obstack_savestring (char* addr, int size)
{
return obstack_copy0 (&myobstack, addr, size);
}
Para liberar objetos en el obstack se emplea obstack_free
void obstack_free (struct obstack* obstack-ptr, void* object)
Si objeto es un puntero nulo, todo lo almacenado en obstack será liberado. Cualquier otro valor debe ser un puntero a un objeto del obstack. Ese objeto será liberado y todos los que se encuentran a continuación de él.
Observa que si object es un puntero nulo, el resultado será un obstack no inicializado. Para liberar todos los objetos del obstack pero dejando el obstack válido para agregar nuevos objetos tenemos que pasarle como object el primer objeto almacenado.
Recuerda que obstack está agrupado en chunks. Si se liberan todos los objetos de un chunk, obstack automaticamente liberará este chunk para que pueda ser utilizado como recurso para otros elementos del programa.
Recordemos que los interfaces definidos en obstack pueden estar definidos como funciones o como macros. Ejemplo:
char* x;
void* (* funcp) ();
/* Use the macro. */
x = (char* ) obstack_alloc (obptr, size);
/* Call the function. */
x = (char* ) (obstack_alloc) (obptr, size);
/* Take the address of the function. */
funcp = obstack_alloc;
Si empleas otro compilador que no sea el de GNU debes tener esto en cuenta.
Para saber más:
GNU C Library Obstacks
Categorías : Programación
Referencias : No hay referencias »




