General Information
Tutorials
Reference Manuals
Libraries
Translation Tasks
Tools
Administration
|
Library ReferenceMemory Object ManagementThis module provides high-speed memory allocation that supports "growing" objects -- objects whose size is not known a priori. Any number of regions can be defined, and storage managed independently by region. Within one region the storage is allocated and freed in a last-in, first-out manner that allows freeing of a large number of objects with a single operation. #include "obstack.h" void obstack_init(ObstackP obstack); void obstack_begin(ObstackP obstack, int size); int obstack_chunk_size(ObstackP obstack); int obstack_alignment_mask(ObstackP obstack); void *obstack_alloc(ObstackP obstack, int size); void *obstack_copy(ObstackP obstack, void *data, int size); void *obstack_copy0(ObstackP obstack, void *data, int size); void *obstack_strcpy(ObstackP obstack, char *data); void obstack_blank(ObstackP obstack, int size); void obstack_grow(ObstackP obstack, void *data, int size); void obstack_grow0(ObstackP obstack, void *data, int size); void obstack_1grow(ObstackP obstack, int data_char); void obstack_ptr_grow(ObstackP obstack, void *data); void obstack_int_grow(ObstackP obstack, int data); void obstack_blank_fast(ObstackP obstack, int size); void obstack_1grow_fast(ObstackP obstack, int data_char); void obstack_ptr_grow_fast(ObstackP obstack, void *data); void obstack_int_grow_fast(ObstackP obstack, int data); void *obstack_finish(ObstackP obstack); void obstack_free(ObstackP obstack, void *block); void *obstack_base(ObstackP obstack); void *obstack_next_free(ObstackP obstack); int obstack_object_size(ObstackP obstack); int obstack_room(ObstackP obstack);
Each region is represented by a data structure of type
Obstack obstk; obstack_init(&obstk);
All the apparent functions operating on regions are macros.
Each takes a pointer of type
_obstack = (address expression); obstack_xxx(_obstack, ...);
The variable A region is a collection of objects managed in a last-in, first-out manner. Each region is independent of the others, and is characterized by a chunk size and an alignment. As objects are added to the collection, blocks of memory of the given chunk size are allocated to hold them. The address of each object in the collection is guaranteed to be divisible by the alignment, which must be a power of 2.
When the storage already available for a collection is insufficient for an
object being added to the collection, then a new chunk is allocated.
The size of the new chunk is the minimum of the chunk size parameter and
twice the size of the object to be added.
Thus the chunk size parameter does not limit the size of an object
that can be stored in the collection, but it does affect the number of
system requests for storage.
If it is not specified when the collection is initialized, a default value
equivalent to one virtual memory page is used.
Chunks are normally allocated by
#define obstack_chunk_alloc MyMalloc #include "obstack.h"
After an object is added to a collection, the next available address is
adjusted to be divisible by the alignment parameter of the collection.
If any address is suitable as an object address
then the alignment should be 1 (the zeroth power of 2).
The default alignment value is that suitable for an object of the primitive
type
The first macro applied to a region must be either
obstack_chunk_size(&obstk) = 0;
The alignment mask is an integer one less than the power of 2 that must
divide each object address.
To make a change in the alignment mask effective, you must create an empty
object.
For example, the following code guarantees that the addresses of
objects subsequently created in the collection
obstack_alignment_mask(&obstk) = 3; (void)obstack_alloc(&obstk, 0); Once a region has been initialized, there are two basic strategies for creating objects: allocation and growth. Objects are allocated when their size is known a priori; they are grown when their size is not known a priori.
Allocation
is the simplest strategy.
Suppose that it was necessary to create an object capable of storing
an array of five integers.
The call
With the growth
strategy, a single object is created by a sequence of macro calls
rather than a single call.
Each call causes the object to grow in size, and possibly establishes some
of the initial contents of the object.
An object can be moved by the module while that object is growing.
The last call in the sequence is to either
An obstack can only accomodate a single growing object at any time.
While that object is growing, no allocation operations may be issued for
the obstack.
After
obstack_init ( A | G+ ( obstack_finish | A ) )*
Macros implementing the growth strategy parallel, for the most part, the
macros implementing the allocation strategy.
They have the same pattern of arguments as their allocation counterparts,
but do not return a pointer to an object because no object exists until the
call of
The special operation
char * obstack_strcpy(obstk, data) ObstackP obstk; char *data; { register char c, *p = data; if (p) while (c = *p++) obstack_1grow(obstk, c); obstack_1grow(obstk, '\0'); return (char *)obstack_finish(obstk); }
The growth macros check that the current chunk has enough space in it for
the growth increment.
If the check fails, a new chunk is allocated and the growing object is
copied into the new chunk.
Two additional operations,
The collection of objects in a region is managed in a last-in,
first-out manner.
This means that there is an operation,
If an
While an object is being grown, its current base address can be obtained
by calling the macro
|