2001-08-21 16:56:08 +04:00
/*
2001-10-04 14:13:07 +04:00
* Copyright ( C ) 2001 Sistina Software ( UK ) Limited .
2001-08-21 16:56:08 +04:00
*
2001-12-20 14:52:54 +03:00
* This file is released under the LGPL .
2001-08-21 16:56:08 +04:00
*/
2001-09-25 16:49:28 +04:00
# ifndef _LVM_POOL_H
# define _LVM_POOL_H
2001-08-21 16:56:08 +04:00
2001-11-15 14:46:00 +03:00
# include <string.h>
2001-08-21 16:56:08 +04:00
# include <stdlib.h>
2002-01-08 13:47:17 +03:00
/*
* The pool allocator is useful when you are going
* to allocate lot ' s of memory , use the memory for
* a bit , and then free the memory in one go . A
* surprising amount of code has this usage
* profile .
*
* You should think of the pool as an infinite ,
* contigous chunk of memory . The front of this
* chunk of memory contains allocated objects , the
* second half is free . pool_alloc grabs the next
* ' size ' bytes from the free half , in effect
* moving it into the allocated half . This
* operation is very efficient .
*
* pool_free free ' s the allocated object * and * all
* objects allocated after it . It is important to
* note this semantic difference from malloc / free .
* This is also extremely efficient , since a
* single pool_free can dispose of a large complex
* object .
*
* pool_destroy free ' s all allocated memory .
*
* eg , If you are building a binary tree in your
* program , and know that you are only ever going
* to insert into your tree , and not delete ( eg ,
* maintaining a symbol table for a compiler ) .
* You can create yourself a pool , allocate the
* nodes from it , and when the tree becomes
* redundant call pool_destroy ( no nasty iterating
* through the tree to free nodes ) .
*
* eg , On the other hand if you wanted to
* repeatedly insert and remove objects into the
* tree , you would be better off allocating the
* nodes from a free list ; you cannot free a
* single arbitrary node with pool .
*/
2001-08-21 16:56:08 +04:00
struct pool ;
/* constructor and destructor */
2001-10-04 14:13:07 +04:00
struct pool * pool_create ( size_t chunk_hint ) ;
void pool_destroy ( struct pool * p ) ;
2001-08-21 16:56:08 +04:00
/* simple allocation/free routines */
void * pool_alloc ( struct pool * p , size_t s ) ;
void * pool_alloc_aligned ( struct pool * p , size_t s , unsigned alignment ) ;
2001-10-12 14:32:06 +04:00
void pool_empty ( struct pool * p ) ;
2001-08-21 16:56:08 +04:00
void pool_free ( struct pool * p , void * ptr ) ;
2001-12-13 19:09:06 +03:00
/*
* Object building routines :
*
* These allow you to ' grow ' an object , useful for
* building strings , or filling in dynamic
* arrays .
*
* It ' s probably best explained with an example :
*
* char * build_string ( struct pool * mem )
* {
* int i ;
* char buffer [ 16 ] ;
*
* if ( ! pool_begin_object ( mem , 128 ) )
* return NULL ;
*
* for ( i = 0 ; i < 50 ; i + + ) {
* snprintf ( buffer , sizeof ( buffer ) , " %d, " , i ) ;
* if ( ! pool_grow_object ( mem , buffer , strlen ( buffer ) ) )
* goto bad ;
* }
*
* // add null
* if ( ! pool_grow_object ( mem , " \0 " , 1 ) )
* goto bad ;
*
* return pool_end_object ( mem ) ;
*
* bad :
*
* pool_abandon_object ( mem ) ;
* return NULL ;
* }
*
* So start an object by calling pool_begin_object
* with a guess at the final object size - if in
* doubt make the guess too small .
*
* Then append chunks of data to your object with
* pool_grow_object . Finally get your object with
* a call to pool_end_object .
*
*/
2001-12-20 14:52:54 +03:00
int pool_begin_object ( struct pool * p , size_t hint ) ;
int pool_grow_object ( struct pool * p , const void * extra , size_t delta ) ;
2001-08-21 16:56:08 +04:00
void * pool_end_object ( struct pool * p ) ;
void pool_abandon_object ( struct pool * p ) ;
/* utilities */
char * pool_strdup ( struct pool * p , const char * str ) ;
static inline void * pool_zalloc ( struct pool * p , size_t s ) {
void * ptr = pool_alloc ( p , s ) ;
if ( ptr )
memset ( ptr , 0 , s ) ;
return ptr ;
}
# endif