From: hgn Date: Wed, 14 Jun 2023 15:33:23 +0000 (+0100) Subject: moev pool here X-Git-Url: https://harrygodden.com/git/?p=vg.git;a=commitdiff_plain;h=48149581c10efff916dfad10f014b90837d531ea moev pool here --- diff --git a/vg_mem_pool.h b/vg_mem_pool.h new file mode 100644 index 0000000..d5742b4 --- /dev/null +++ b/vg_mem_pool.h @@ -0,0 +1,106 @@ +#ifndef VG_MEM_POOL_H +#define VG_MEM_POOL_H + +/* pool for loaded addons */ +#define VG_POOL_NIL 0xffff + +typedef struct vg_pool vg_pool; +typedef struct vg_pool_node vg_pool_node; + +/* this goes in your structures */ +struct vg_pool_node { + u16 l, r, ref_count; +}; + +struct vg_pool { + void *buffer; /* array which holds the real data */ + u16 count, head, tail; + size_t stride, offset; +}; + +static vg_pool_node *vg_pool_nodeptr ( vg_pool *pool, void *item ); +static void *vg_pool_item ( vg_pool *pool, u16 index ); +static void vg_pool_init ( vg_pool *pool ); +static u16 addon_item_index ( vg_pool *pool, void *item ); +static void *vg_pool_lru ( vg_pool *pool ); +static void vg_pool_watch ( vg_pool *pool, void *item ); +static void vg_pool_unwatch ( vg_pool *pool, void *item ); + +/* implementation + * -------------------------------------------------------------------------- */ + +static vg_pool_node *vg_pool_nodeptr( vg_pool *pool, void *item ){ + if( !item ) return NULL; + else return item + pool->offset; +} + +static void *vg_pool_item( vg_pool *pool, u16 index ){ + if( index == VG_POOL_NIL ) return NULL; + else return pool->buffer + pool->stride*(size_t)index; +} + +static void vg_pool_init( vg_pool *pool ){ + pool->head = 0; + pool->tail = pool->count -1; + for( i32 ib=0; ib < pool->count; ib++ ){ + void *vb = vg_pool_item( pool, ib ); + vg_pool_node *nb = vg_pool_nodeptr( pool, vb ); + + i32 ia = ib-1, ic = ib+1; + nb->l = ia>=0? ia: VG_POOL_NIL, + nb->r = iccount? ic: VG_POOL_NIL; + nb->ref_count = 0; + } +} + +static u16 addon_item_index( vg_pool *pool, void *item ){ + return (item - pool->buffer) / pool->stride; +} + +static void *vg_pool_lru( vg_pool *pool ){ + u16 head = pool->head; + if( head == VG_POOL_NIL ) return NULL; + + void *item = vg_pool_item( pool, head ); + vg_pool_node *node = vg_pool_nodeptr( pool, item ); + + if( pool->head == pool->tail ) pool->tail = VG_POOL_NIL; + pool->head = node->r; + + node->l = VG_POOL_NIL; + node->r = VG_POOL_NIL; + return item; +} + +static void vg_pool_watch( vg_pool *pool, void *item ){ + vg_pool_node *node = vg_pool_nodeptr( pool, item ); + + if( node->ref_count >= 128 ) + 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 */ +static void vg_pool_unwatch( vg_pool *pool, void *item ){ + vg_pool_node *node = vg_pool_nodeptr( pool, item ); + + if( node->ref_count == 0 ) + vg_fatal_error( "pool unwatch missmatch (no watchers)\n" ); + + node->ref_count --; + if( !node->ref_count ){ + void *item_head = vg_pool_item( pool, pool->head ), + *item_tail = vg_pool_item( pool, pool->tail ); + vg_pool_node *head = vg_pool_nodeptr( pool, item_head ), + *tail = vg_pool_nodeptr( pool, item_tail ); + + u16 index = addon_item_index( pool, item ); + if( tail ) tail->r = index; + node->l = pool->tail; + pool->tail = index; + if( !head ) pool->head = index; + } +} + +#endif /* VG_MEM_POOL_H */