#include <blockpool.h>
Public Types | |
typedef struct block_pool::block_chain_struct | block_chain |
typedef for memory block chain. More... | |
enum | bogus { one_kay = 1024, page_size = (4 * one_kay), max_block_multiple = 256, last_enum } |
the largest block of memory that can be allocated is the page_size * max_block_multiple. More... | |
Public Methods | |
block_pool (void) | |
constructor does nothing, since all the class variables are static. More... | |
void | free_pool (void) |
block_pool::free_pool. More... | |
void* | pool_alloc (unsigned int block_size) |
pool_alloc. More... | |
void | print_block_pool_info (FILE *fp=stdout) |
print_block_pool_info. More... | |
Protected Methods | |
virtual void* | MemAlloc (unsigned int n_bytes) |
Allocate memory using calloc. More... | |
virtual void | MemFree (void *addr) |
Free memory that has been allocated with MemAlloc. More... | |
Private Methods | |
block_chain* | new_block (unsigned int block_size) |
new_block. More... | |
void* | add_block (unsigned int block_size) |
block_pool::add_block Add a new memory block to the memory pool. More... | |
void | init_pool (void) |
block_pool::init_pool. More... | |
Static Private Attributes | |
unsigned int | alloc_gran = (unsigned int)block_pool::page_size |
allocation granularity. More... | |
block_chain* | block_list_start = 0 |
start of the block list for this pool. More... | |
block_chain* | current_block = 0 |
current block memory is being allocated from. More... |
A memory pool is allocated in blocks and smaller chunks of memory are allocated from these blocks. Instead of calling a set of class destructors (which is time consuming) the memory pool allows all the objects allocated in the memory pool to be destroyed at once. This provide a sort of "poorman's garbage collector. Deallocating memory in a single place simplifies the software structure, since allocation can be scattered throughout the code without worry about deallocation.
This is a simplified version of a low level memory allocator that can be used to create multiple memory pools. In this class the class variables are static and shared by all instances of the class. This allows the class to be declared locally to allocate memory, but the state remains global. This makes the local instance a window into the global state. The limitation is that only one memory pool can be used.
Originally written November, 1996
Revised for the wavelet packet transform code March 2002
Definition at line 66 of file blockpool.h.
|
typedef for memory block chain.
|
|
the largest block of memory that can be allocated is the page_size * max_block_multiple.
Definition at line 70 of file blockpool.h. 00070 { one_kay = 1024, 00071 page_size = (4 * one_kay), /* 4 Kb */ 00072 max_block_multiple = 256, /* 1 Mb */ 00073 last_enum 00074 } bogus; |
|
constructor does nothing, since all the class variables are static.
Definition at line 145 of file blockpool.h. 00145 {} |
|
Allocate memory using calloc. The POSIX calloc function sets the memory to zero (in contrast to malloc which allocates the memory without initializing it.
include <stdlib> void *calloc( size_t num, size_t size ); The arguments to calloc are:
num: number of elements The argument to MemAlloc is the size, in bytes to allocate. Definition at line 128 of file blockpool.h. Referenced by new_block().
00129 { 00130 void *rtn = calloc( n_bytes, 1 ); 00131 return rtn; 00132 } |
|
Free memory that has been allocated with MemAlloc.
Definition at line 136 of file blockpool.h. Referenced by free_pool().
00137 { 00138 free( addr ); 00139 } |
|
block_pool::add_block Add a new memory block to the memory pool. This function is called when the amount of memory requested by pool_alloc will not fit in the current block. Definition at line 141 of file blockpool.cpp. Referenced by pool_alloc().
00142 { 00143 block_chain *block = 0; 00144 block_chain *last_block; 00145 00146 last_block = current_block; 00147 block = new_block( block_size ); 00148 Chain_next(current_block) = block; 00149 current_block = block; 00150 00151 return (void *)block; 00152 } // block_chain::add_block |
|
Walk through the block chain and deallocate the blocks. Note that the block chain structures and the allocatible memory is contained within a single allocated block. The block_chain structure is at the start of this block so passing its address to the memory deallocation function deallocates both the block chain structure and the allocatible memory Definition at line 219 of file blockpool.cpp. Referenced by main().
00220 { 00221 block_chain *tmp; 00222 00223 while (block_list_start != 0) { 00224 tmp = block_list_start; 00225 block_list_start = Chain_next(block_list_start); 00226 MemFree( (void *)tmp ); 00227 } 00228 } // free_pool |
|
This function is automatically called to initialize the block_pool object when the "current_block" pointer is null. Definition at line 66 of file blockpool.cpp. Referenced by pool_alloc().
00067 { 00068 00069 block_chain *new_link; 00070 00071 new_link = new_block( alloc_gran ); 00072 block_list_start = new_link; 00073 current_block = new_link; 00074 } /* init_pool */ |
|
new_block. The new_block function is the "root" memory allocator for the block_pool object. The amount of memory allocated is rounded up to the next "block_size" boundary. Both the block_chain structure and the allocatible memory are allocated from a single block that is a multiple of the page size. This should avoid fragmentation in the system memory allocator. The "page" referenced here is a virtual memory page. This version of the code does not actually check the system page size, but assumes a 4Kb page. Definition at line 94 of file blockpool.cpp. Referenced by add_block(), and init_pool().
00095 { 00096 const unsigned int max_block_size = max_block_multiple * page_size; 00097 block_chain *new_link = 0; 00098 unsigned int alloc_amt, total_alloc; 00099 00100 // add in the memory needed for the block_chain structure 00101 total_alloc = block_size + sizeof(block_chain); 00102 if (total_alloc < alloc_gran) 00103 alloc_amt = alloc_gran; 00104 else { 00105 // its larger than the minimum allocation granularity, so round 00106 // up the the nearest page. 00107 alloc_amt = ((total_alloc + (page_size-1))/page_size) * page_size; 00108 } 00109 00110 if (alloc_amt <= max_block_size) { 00111 00112 /* Allocate memory for both the block_chain structure and the memory 00113 block */ 00114 new_link = (block_chain *)MemAlloc( alloc_amt ); 00115 00116 // The new memory block starts after the block_chain structure 00117 Chain_block(new_link) = (void *)(((unsigned int)new_link) + sizeof(block_chain)); 00118 00119 assert( alloc_amt >= block_size ); 00120 00121 Chain_bytes_used(new_link) = 0; 00122 Chain_block_size(new_link) = alloc_amt - sizeof(block_chain); 00123 Chain_next(new_link) = 0; 00124 } 00125 else { 00126 printf("block_pool::new_block: allocation request too large\n"); 00127 } 00128 00129 return new_link; 00130 } // block_chain::new_block |
|
pool_alloc. Allocate memory from the memory pool. The pool_alloc and free_pool functions do memory allocation and deallocation. This function is called to allocate memory from the memory pool. If there is enough free memory in the current block to satisify the memory request, memory is allocated from the current block and the amount of free memory is updated. If the current block does not have enough memory, add_block is called to allocate a new memory block which will be large enough. Definition at line 171 of file blockpool.cpp. Referenced by queueElem::operator new(), packdata::operator new(), packcontainer_int::operator new(), packcontainer::operator new(), LIST::list_type::operator new(), FIFO_LIST::list_type::operator new(), packcontainer::packcontainer(), packcontainer_int::packcontainer_int(), packfreq::packfreq(), packtree::packtree(), packtree_int::packtree_int(), invpacktree_int::reduce(), invpacktree::reduce(), and testWaveletTrans().
00172 { 00173 const unsigned int align = sizeof( int ); 00174 void *addr = 0; 00175 unsigned int amt_free; 00176 00177 /* the number of bytes allocated must be a multiple of the align 00178 size */ 00179 num_bytes = ((num_bytes + (align-1))/align) * align; 00180 00181 if (current_block == 0) { 00182 init_pool(); 00183 } 00184 00185 amt_free = Chain_block_size(current_block) - Chain_bytes_used(current_block); 00186 00187 if (num_bytes > amt_free) { 00188 if (add_block( num_bytes ) != 0) { 00189 amt_free = Chain_block_size(current_block); 00190 } 00191 } 00192 00193 if (amt_free >= num_bytes) { 00194 addr = (void *)((unsigned int)Chain_block(current_block) + Chain_bytes_used(current_block)); 00195 Chain_bytes_used(current_block) += num_bytes; 00196 } 00197 else { 00198 printf("block_pool::block_alloc: allocation error\n"); 00199 exit(1); 00200 } 00201 return addr; 00202 } // block_pool::pool_alloc |
|
print_block_pool_info. Print information about the block pool Definition at line 238 of file blockpool.cpp. 00239 { 00240 int total_allocated = 0; 00241 int total_unused = 0; 00242 block_chain *ptr = block_list_start; 00243 00244 fprintf(fp, "Minimum memory allocation size: %d\n", alloc_gran ); 00245 fprintf(fp, "Page size: %d\n", (unsigned int)page_size ); 00246 fprintf(fp, "[block size, bytes_used]\n"); 00247 while (ptr != 0) { 00248 fprintf(fp, "[%4d, %4d]", Chain_block_size(ptr), Chain_bytes_used(ptr)); 00249 total_allocated += Chain_bytes_used(ptr); 00250 total_unused += (Chain_block_size(ptr) - Chain_bytes_used(ptr)); 00251 if (Chain_next(ptr) != 0) { 00252 fprintf(fp, ", "); 00253 } 00254 else { 00255 fprintf(fp, "\n"); 00256 } 00257 ptr = Chain_next(ptr); 00258 } // while 00259 fprintf(fp, "Total allocated = %5d, total unused = %3d\n", total_allocated, 00260 total_unused ); 00261 } |
|
allocation granularity.
Definition at line 93 of file blockpool.h. |
|
start of the block list for this pool.
Definition at line 96 of file blockpool.h. |
|
current block memory is being allocated from.
Definition at line 99 of file blockpool.h. |