#ifndef VG_MEM_POOL_H
#define VG_MEM_POOL_H
-/* pool for loaded addons */
-#define VG_POOL_NIL 0xffff
+#include "vg_mem.h"
+#include "stddef.h"
+#include "vg_stdint.h"
typedef struct vg_pool vg_pool;
typedef struct vg_pool_node vg_pool_node;
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 == 0) || (id > pool->count) )
+ return NULL;
+
+ 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;
- if( pool->head == pool->tail ) pool->tail = VG_POOL_NIL;
- pool->head = node->r;
+ node->r = 0;
+ node->l = 0;
+}
- node->l = VG_POOL_NIL;
- node->r = VG_POOL_NIL;
- return item;
+static u16 vg_pool_lru( vg_pool *pool ){
+ u16 head = pool->head;
+ if( !head ) return 0;
+
+ 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" );
}
/* 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;
}
}