moev pool here
authorhgn <hgodden00@gmail.com>
Wed, 14 Jun 2023 15:33:23 +0000 (16:33 +0100)
committerhgn <hgodden00@gmail.com>
Wed, 14 Jun 2023 15:33:23 +0000 (16:33 +0100)
vg_mem_pool.h [new file with mode: 0644]

diff --git a/vg_mem_pool.h b/vg_mem_pool.h
new file mode 100644 (file)
index 0000000..d5742b4
--- /dev/null
@@ -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 = ic<pool->count? 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 */