logger update
[vg.git] / vg_mem_pool.h
index d5742b48009bf792dba7bfe6f7d187a655f75e83..2326a3f469f70684c38852ffd47adde68053f2e4 100644 (file)
@@ -1,8 +1,9 @@
 #ifndef VG_MEM_POOL_H
 #define VG_MEM_POOL_H
 
-/* pool for loaded addons */
-#define VG_POOL_NIL 0xffff
+#include "vg/vg_mem.h"
+#include "stddef.h"
+#include "vg/vg_stdint.h"
 
 typedef struct vg_pool vg_pool;
 typedef struct vg_pool_node vg_pool_node;
@@ -18,62 +19,75 @@ struct vg_pool {
    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 vg_pool_node *vg_pool_nodeptr  ( vg_pool *pool, u16 id );
+static void         *vg_pool_item     ( vg_pool *pool, u16 id );
 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 );
+static u16           vg_pool_id       ( vg_pool *pool, void *item );
+static u16           vg_pool_lru      ( vg_pool *pool );
+static void          vg_pool_watch    ( vg_pool *pool, u16 id );
+static void          vg_pool_unwatch  ( vg_pool *pool, u16 id );
 
 /* implementation 
  * -------------------------------------------------------------------------- */
 
-static vg_pool_node *vg_pool_nodeptr( vg_pool *pool, void *item ){
-   if( !item ) return NULL;
-   else return item + pool->offset;
+static 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;
+   }
 }
 
-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_item( vg_pool *pool, u16 id ){
+   if( !id ) return NULL;
+   else return pool->buffer + pool->stride*(size_t)(id-1);
 }
 
 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;
+   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;
    }
 }
 
-static u16 addon_item_index( vg_pool *pool, void *item ){
-   return (item - pool->buffer) / pool->stride;
+static u16 vg_pool_id( vg_pool *pool, void *item ){
+   return ((item - pool->buffer) / pool->stride) + 1;
 }
 
-static void *vg_pool_lru( vg_pool *pool ){
-   u16 head = pool->head;
-   if( head == VG_POOL_NIL ) return NULL;
+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 );
 
-   void *item = vg_pool_item( pool, head );
-   vg_pool_node *node = vg_pool_nodeptr( pool, item );
+   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;
+}
 
-   if( pool->head == pool->tail ) pool->tail = VG_POOL_NIL;
-   pool->head = node->r;
+static u16 vg_pool_lru( vg_pool *pool ){
+   u16 head = pool->head;
+   if( !head ) return 0;
 
-   node->l = VG_POOL_NIL;
-   node->r = VG_POOL_NIL;
-   return item;
+   vg_pool_unlink( pool, head );
+   return head;
 }
 
-static void vg_pool_watch( vg_pool *pool, void *item ){
-   vg_pool_node *node = vg_pool_nodeptr( pool, item );
+static 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 >= 128 )
       vg_fatal_error( "pool watch missmatch (limit is 128)\n" );
@@ -82,24 +96,21 @@ static void vg_pool_watch( vg_pool *pool, void *item ){
 }
 
 /* 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 );
+static 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 ){
-      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 );
+      vg_pool_node *head = vg_pool_nodeptr( pool, pool->head ),
+                   *tail = vg_pool_nodeptr( pool, pool->tail );
       
-      u16 index = addon_item_index( pool, item );
-      if( tail ) tail->r = index;
+      if( tail ) tail->r = id;
       node->l = pool->tail;
-      pool->tail = index;
-      if( !head ) pool->head = index;
+      pool->tail = id;
+      if( !head ) pool->head = id;
    }
 }