ctlnew.c File Reference

Safe C allocators with 'exception handling'. More...

#include "ctl/ctldef.h"
#include "ctl/ll.h"
#include "ctl/debug.h"

Include dependency graph for ctlnew.c:

Go to the source code of this file.

Data Structures

struct  ctl_pool_base_node
 A member of a pool's free list. More...
struct  ctl_pool_base_block
 A block allocation made when a pool grew This contains a link to block data and a certain number of unit-sized blocks of memory. Basically, it's part of a singly linked list of blocks that were allocated as a given pool grew. More...

Defines

#define ctl_xenum(def)   ppConcat(ctl_xenum_,def)
#define ctl_xtab_size(def)   ppConcat(ctl_xtab_size_,def)
#define ctl_xttab_type(def)   ppConcat(ctl_xttab_type_,def)
#define ctl_xtab_type_space(size, delta)   void
#define CTL_META_LIST(def)

Typedefs

typedef void(* destruct_t )(void *)
 Keeps track of CTL allocations/sizes.

Functions

ctl_newhandler ctl_set_new_handler (ctl_newhandler handler)
 Set a newhandler.
size_t ctl_memory_dump (uint32 logmask)
 If we have memory tracking, we can dump a list of what's allocated.
size_t ctl_pool_dump (uint32 logmask)
 Dump a list of active memory pools.
void ctl_destroy_all_pools (void)
 Dump a list of active memory pools.
void ctl_pool_base_init (ctl_pool_base *pool, size_t unitSize, size_t delta, const char *name)
 Initialize a ctl_pool_base.
void ctl_pool_base_grow (ctl_pool_base *pool, size_t delta)
 Force a pool to grow to an expected size.
void ctl_pool_base_destroy (ctl_pool_base *pool)
 Free a pool - mainly used for onexit destruction.
void * ctl_pool_base_alloc (ctl_pool_base *pool)
 Allocate a block of memory from this pool.
void ctl_pool_base_free (ctl_pool_base *pool, void *ptr)
 Return a pointer back to memory pool.


Detailed Description

Safe C allocators with 'exception handling'.

Author:
David Mace

Definition in file ctlnew.c.


Define Documentation

#define CTL_META_LIST ( def   ) 

Value:

def( space(16, 64) )\
    def( space(32, 32) )\
    def( space(64, 16) )\
    def( space(96, 16) )\
    def( space(128, 16) )\
    def( space(192, 16) )\
    def( space(256, 8) )\
    def( space(384, 8) )\
    def( space(512, 8) )\
    def( space(640, 8) )\
    def( space(768, 4) )\
    def( space(1024, 4) )\
    def( space(1536, 4) )\
    def( space(2048, 4) )\
    def( space(3072, 4) )\
    def( space(4096, 4) )\
    def( space(6144, 3) )\
    def( space(8192, 2) )\
    def( object(type, 256) )\
    def( object(type, 256) )\
Define memory pools and growth rates

Definition at line 554 of file ctlnew.c.

#define ctl_xenum ( def   )     ppConcat(ctl_xenum_,def)

Construct an enum for allocation types/sizes

Definition at line 527 of file ctlnew.c.

#define ctl_xtab_size ( def   )     ppConcat(ctl_xtab_size_,def)

Construct a table for allocating by size

Definition at line 534 of file ctlnew.c.

#define ctl_xtab_type_space ( size,
delta   )     void

Get type

Definition at line 548 of file ctlnew.c.

#define ctl_xttab_type ( def   )     ppConcat(ctl_xttab_type_,def)

Construct a table for allocating by type

Definition at line 541 of file ctlnew.c.


Function Documentation

size_t ctl_memory_dump ( uint32  logmask  ) 

If we have memory tracking, we can dump a list of what's allocated.

Parameters:
handler Your provided function gets called back to tell where and how much memory was allocated
Returns:
count of memory blocks dumped (should be zero as application exits)

Definition at line 325 of file ctlnew.c.

References dll_foreach.

00326 {
00327     size_t count = 0;
00328     dll_foreach( AllocList,allocated, memoryList, curr )
00329     {
00330         count++;
00331         if( curr->check == HEAD_CHECK  && curr->check2 == HEAD_CHECK )
00332         {
00333             LOG( logmask, "%s: %u\n", curr->szFileLine, curr->size );
00334             _ctlvalidate( ALLOC_OFFSET(curr), "ctl_memory_dump" );
00335         }
00336         else
00337         {
00338             /* We can't trust any pointer between bad header checks */
00339             LOG( LOG_ERROR, "Bad memory node link\n" );
00340             break;
00341         }
00342     }
00343     return count;
00344 }

void* ctl_pool_base_alloc ( ctl_pool_base pool  ) 

Allocate a block of memory from this pool.

Parameters:
pool Instance of pool to initialize
Returns:
A buffer containing pool data

Definition at line 488 of file ctlnew.c.

References ctl_pool_base::cAlloc, ctl_pool_base::cFree, ctl_pool_base_grow(), ctl_pool_base::delta, ctl_pool_base::freelist, ctl_pool_base_node::pool, sll_erase, and ctl_pool_base_node::specialization.

00489 {
00490     struct ctl_pool_base_node* pfree = pool->freelist;
00491     if( NULL == pfree )
00492     {
00493         ctl_pool_base_grow( pool, pool->delta );
00494         pfree = pool->freelist;
00495     }
00496     pool->cFree--;
00497     pool->cAlloc++;
00498     sll_erase(struct ctl_pool_base_node,specialization.free, pool->freelist, pfree );
00499     ppDebug(pfree->specialization.pool = pool);
00500     return pfree+1;
00501 }

Here is the call graph for this function:

void ctl_pool_base_destroy ( ctl_pool_base pool  ) 

Free a pool - mainly used for onexit destruction.

Parameters:
pool Instance of pool to initialize

Definition at line 467 of file ctlnew.c.

References ctl_pool_base::blocks, ctl_free, ctl_pool_base_block::next, and sll_erase.

Referenced by ctl_destroy_all_pools().

00468 {
00469     /* Walk through each of our pool blocks, freeing the base pointer */
00470     struct ctl_pool_base_block* curr = pool->blocks;
00471     pool->blocks = NULL;
00472     while( curr )
00473     {
00474         struct ctl_pool_base_block* next = curr->next;
00475         ctl_free( curr );
00476         curr = next;
00477     }
00478     /* Remove from active pool list; this instance may be falling out of scope, or being freed */
00479     sll_erase(ctl_pool_base,poolList, ctl_pool_base_list, pool );
00480     memset(pool,0,sizeof(*pool));
00481 }

void ctl_pool_base_free ( ctl_pool_base pool,
void *  ptr 
)

Return a pointer back to memory pool.

Parameters:
pool Pool pointer came from
ptr Pointer to free

Definition at line 508 of file ctlnew.c.

References assert, assertobjptr, assertptr, ctl_pool_base::cAlloc, ctl_pool_base::cFree, ctl_pool_base::freelist, ctl_pool_base_node::pool, sll_push_front, and ctl_pool_base_node::specialization.

00509 {
00510     struct ctl_pool_base_node* pfree = (struct ctl_pool_base_node*)ptr-1;
00511     assertobjptr(pool);
00512     assertptr(ptr,4);
00513     
00514     /* We should not be expecting a free if nothing has been allocated from this pool */
00515     assert( pool->cAlloc > 0 );
00516     
00517     /* We stuck those pointers into the memory link nodes for a reason. */
00518     assert( pfree->specialization.pool == pool );
00519 
00520     /* Add it back to the free list */
00521     pool->cFree++;
00522     pool->cAlloc--;
00523     sll_push_front(struct ctl_pool_base_node,specialization.free, pool->freelist, pfree );
00524 }

void ctl_pool_base_grow ( ctl_pool_base pool,
size_t  delta 
)

Force a pool to grow to an expected size.

Parameters:
pool Instance of pool to initialize
delta How many units to grow now

Definition at line 438 of file ctlnew.c.

References ctl_pool_base::blocks, ctl_pool_base::cFree, ctl_malloc, ctl_pool_base::freelist, ctl_pool_base_block::next, sll_push_front, and ctl_pool_base::unit.

Referenced by ctl_pool_base_alloc().

00439 {
00440     /* Need to allocate a new block */
00441     struct ctl_pool_base_block* block;
00442     size_t unitSize = roundup(pool->unit, sizeof( struct ctl_pool_base_node )) + sizeof( struct ctl_pool_base_node );
00443     size_t size = sizeof(struct ctl_pool_base_block) + (unitSize * delta);
00444     ctl_malloc( block, size );
00445     /* Add to list of active pools */
00446     if( !pool->blocks )
00447         sll_push_front(ctl_pool_base,poolList, ctl_pool_base_list, pool );
00448     sll_push_front(struct ctl_pool_base_block,next, pool->blocks, block );
00449     {
00450         uint8* pCurr = (uint8*)block+size;
00451         size_t curr = delta;
00452         while( curr-- )
00453         {
00454             struct ctl_pool_base_node* pfree;
00455             pCurr -= unitSize;
00456             pfree = (struct ctl_pool_base_node*)pCurr;
00457             sll_push_front(struct ctl_pool_base_node,specialization.free, pool->freelist, pfree );
00458         }
00459         pool->cFree += delta;
00460     }
00461 }

void ctl_pool_base_init ( ctl_pool_base pool,
size_t  unitSize,
size_t  delta,
const char *  name 
)

Initialize a ctl_pool_base.

Parameters:
pool Instance of pool to initialize
unitSize Size of an allocation unit
delta How many units to grow at a time
name Name of this pool

Definition at line 417 of file ctlnew.c.

References assertconst, assertobjptr, ctl_pool_base::blocks, ctl_pool_base::cAlloc, ctl_pool_base::cFree, ctl_pool_base::delta, ctl_pool_base::freelist, ctl_pool_base::name, ctl_pool_base::poolList, and ctl_pool_base::unit.

00418 {
00419     assertobjptr(pool);
00420     assertconst(name,1);
00421 
00422     /* Initialize a pool */
00423     pool->freelist = NULL;
00424     pool->blocks = NULL;
00425     pool->poolList = NULL;
00426     pool->name = name;
00427     /* Units we deal with are allocated in values divisible by sizeof ctl_pool_base_node; setting aside room for one ctl_pool_base_node as well */
00428     pool->unit = unitSize;
00429     pool->delta = delta;
00430     pool->cFree = pool->cAlloc = 0;
00431 }

ctl_newhandler ctl_set_new_handler ( ctl_newhandler  handler  ) 

Set a newhandler.

Set a handler for allocation failures.

Definition at line 23 of file ctlnew.c.

References assertcodeptr.

00024 {
00025     ctl_newhandler ret = curr_newhandler;
00026     curr_newhandler = handler ? handler : ctl_defaultnewhandler;
00027     assertcodeptr(curr_newhandler);
00028     return ret;
00029 }


Generated on Fri Jan 2 15:28:35 2009 for Squat by  doxygen 1.5.6