bad char
[vg.git] / vg_mem_pool.h
1 #ifndef VG_MEM_POOL_H
2 #define VG_MEM_POOL_H
3
4 #include "vg_mem.h"
5 #include "stddef.h"
6 #include "vg_stdint.h"
7
8 typedef struct vg_pool vg_pool;
9 typedef struct vg_pool_node vg_pool_node;
10
11 /* this goes in your structures */
12 struct vg_pool_node {
13 u16 l, r, ref_count;
14 };
15
16 struct vg_pool {
17 void *buffer; /* array which holds the real data */
18 u16 count, head, tail;
19 size_t stride, offset;
20 };
21
22 static vg_pool_node *vg_pool_nodeptr ( vg_pool *pool, u16 id );
23 static void *vg_pool_item ( vg_pool *pool, u16 id );
24 static void vg_pool_init ( vg_pool *pool );
25 static u16 vg_pool_id ( vg_pool *pool, void *item );
26 static u16 vg_pool_lru ( vg_pool *pool );
27 static void vg_pool_watch ( vg_pool *pool, u16 id );
28 static void vg_pool_unwatch ( vg_pool *pool, u16 id );
29
30 /* implementation
31 * -------------------------------------------------------------------------- */
32
33 static vg_pool_node *vg_pool_nodeptr( vg_pool *pool, u16 id ){
34 if( !id ) return NULL;
35 else {
36 return pool->buffer + (pool->stride*(id-1)) + pool->offset;
37 }
38 }
39
40 static void *vg_pool_item( vg_pool *pool, u16 id ){
41 if( (id == 0) || (id > pool->count) )
42 return NULL;
43
44 return pool->buffer + pool->stride*(size_t)(id-1);
45 }
46
47 static void vg_pool_init( vg_pool *pool ){
48 pool->head = 1;
49 pool->tail = pool->count;
50 for( u16 ib=1; ib <= pool->count; ib++ ){
51 vg_pool_node *nb = vg_pool_nodeptr( pool, ib );
52
53 u16 ia = ib-1, ic = ib+1;
54 nb->l = ia;
55 nb->r = ic<=pool->count? ic: 0;
56 nb->ref_count = 0;
57 }
58 }
59
60 static u16 vg_pool_id( vg_pool *pool, void *item ){
61 return ((item - pool->buffer) / pool->stride) + 1;
62 }
63
64 static void vg_pool_unlink( vg_pool *pool, u16 id ){
65 vg_pool_node *node = vg_pool_nodeptr( pool, id );
66 vg_pool_node *l = vg_pool_nodeptr( pool, node->l ),
67 *r = vg_pool_nodeptr( pool, node->r );
68
69 if( pool->head == id ) pool->head = node->r;
70 if( pool->tail == id ) pool->tail = node->l;
71
72 if( l ) l->r = node->r;
73 if( r ) r->l = node->l;
74
75 node->r = 0;
76 node->l = 0;
77 }
78
79 static u16 vg_pool_lru( vg_pool *pool ){
80 u16 head = pool->head;
81 if( !head ) return 0;
82
83 vg_pool_unlink( pool, head );
84 return head;
85 }
86
87 static void vg_pool_watch( vg_pool *pool, u16 id ){
88 vg_pool_node *node = vg_pool_nodeptr( pool, id );
89
90 if( !node->ref_count ){
91 vg_pool_unlink( pool, id );
92 }
93
94 if( node->ref_count >= 128 )
95 vg_fatal_error( "pool watch missmatch (limit is 128)\n" );
96
97 node->ref_count ++;
98 }
99
100 /* if after this no more watches, places back into the volatile list */
101 static void vg_pool_unwatch( vg_pool *pool, u16 id ){
102 vg_pool_node *node = vg_pool_nodeptr( pool, id );
103
104 if( node->ref_count == 0 )
105 vg_fatal_error( "pool unwatch missmatch (no watchers)\n" );
106
107 node->ref_count --;
108 if( !node->ref_count ){
109 vg_pool_node *head = vg_pool_nodeptr( pool, pool->head ),
110 *tail = vg_pool_nodeptr( pool, pool->tail );
111
112 if( tail ) tail->r = id;
113 node->l = pool->tail;
114 pool->tail = id;
115 if( !head ) pool->head = id;
116 }
117 }
118
119 #endif /* VG_MEM_POOL_H */