X-Git-Url: https://harrygodden.com/git/?p=vg.git;a=blobdiff_plain;f=vg_mem_pool.c;fp=vg_mem_pool.c;h=1fe3302fd960bb1349f6981cbc5310f619204955;hp=0000000000000000000000000000000000000000;hb=3b14f3dcd5bf9dd3c85144f2123d667bfa4bb63f;hpb=fce86711735b15bff37de0f70716808410fcf269 diff --git a/vg_mem_pool.c b/vg_mem_pool.c new file mode 100644 index 0000000..1fe3302 --- /dev/null +++ b/vg_mem_pool.c @@ -0,0 +1,100 @@ +#include "vg_platform.h" +#include "vg_mem.h" +#include "vg_mem_pool.h" +#include + +/* implementation + * -------------------------------------------------------------------------- */ + +vg_pool_node *vg_pool_nodeptr( vg_pool *pool, u16 id ){ + if( !id ) return NULL; + else { + return pool->buffer + (pool->stride*(id-1)) + pool->offset; + } +} + +void *vg_pool_item( vg_pool *pool, u16 id ) +{ + if( (id == 0) || (id > pool->count) ) + return NULL; + + return pool->buffer + pool->stride*(size_t)(id-1); +} + +void vg_pool_init( vg_pool *pool ) +{ + pool->head = 1; + pool->tail = pool->count; + for( u16 ib=1; ib <= pool->count; ib++ ){ + vg_pool_node *nb = vg_pool_nodeptr( pool, ib ); + + u16 ia = ib-1, ic = ib+1; + nb->l = ia; + nb->r = ic<=pool->count? ic: 0; + nb->ref_count = 0; + } +} + +u16 vg_pool_id( vg_pool *pool, void *item ) +{ + return ((item - pool->buffer) / pool->stride) + 1; +} + +static void vg_pool_unlink( vg_pool *pool, u16 id ) +{ + vg_pool_node *node = vg_pool_nodeptr( pool, id ); + vg_pool_node *l = vg_pool_nodeptr( pool, node->l ), + *r = vg_pool_nodeptr( pool, node->r ); + + if( pool->head == id ) pool->head = node->r; + if( pool->tail == id ) pool->tail = node->l; + + if( l ) l->r = node->r; + if( r ) r->l = node->l; + + node->r = 0; + node->l = 0; +} + +u16 vg_pool_lru( vg_pool *pool ) +{ + u16 head = pool->head; + if( !head ) return 0; + + vg_pool_unlink( pool, head ); + return head; +} + +void vg_pool_watch( vg_pool *pool, u16 id ) +{ + vg_pool_node *node = vg_pool_nodeptr( pool, id ); + + if( !node->ref_count ){ + vg_pool_unlink( pool, id ); + } + + if( node->ref_count == 0xffff ) + vg_fatal_error( "pool watch missmatch (limit is 128)\n" ); + + node->ref_count ++; +} + +/* if after this no more watches, places back into the volatile list */ +void vg_pool_unwatch( vg_pool *pool, u16 id ) +{ + vg_pool_node *node = vg_pool_nodeptr( pool, id ); + + if( node->ref_count == 0 ) + vg_fatal_error( "pool unwatch missmatch (no watchers)\n" ); + + node->ref_count --; + if( !node->ref_count ){ + vg_pool_node *head = vg_pool_nodeptr( pool, pool->head ), + *tail = vg_pool_nodeptr( pool, pool->tail ); + + if( tail ) tail->r = id; + node->l = pool->tail; + pool->tail = id; + if( !head ) pool->head = id; + } +}