put in its own file
[carveJwlIkooP6JGAAIwe30JlM.git] / addon_cache.c
1 #ifndef ADDON_CACHE_C
2 #define ADDON_CACHE_C
3
4 #include "addon_cache.h"
5
6 static addon_cache_node *addon_cache_nodeptr( addon_cache *cache, void *item ){
7 if( !item ) return NULL;
8 else return item + cache->offset;
9 }
10
11 static void *addon_cache_item( addon_cache *cache, u16 index ){
12 if( index == ADDON_CACHE_NIL ) return NULL;
13 else return cache->buffer + cache->stride*(size_t)index;
14 }
15
16 static void addon_cache_init( addon_cache *cache ){
17 cache->head = 0;
18 cache->tail = cache->count -1;
19 for( i32 ib=0; ib < cache->count; ib++ ){
20 void *vb = addon_cache_item( cache, ib );
21 addon_cache_node *nb = addon_cache_nodeptr( cache, vb );
22
23 i32 ia = ib-1, ic = ib+1;
24 nb->l = ia>=0? ia: ADDON_CACHE_NIL,
25 nb->r = ic<cache->count? ic: ADDON_CACHE_NIL;
26 nb->ref_count = 0;
27 }
28 }
29
30 static u16 addon_item_index( addon_cache *cache, void *item ){
31 return (item - cache->buffer) / cache->stride;
32 }
33
34 static void *addon_cache_lru( addon_cache *cache ){
35 u16 head = cache->head;
36 if( head == ADDON_CACHE_NIL ) return NULL;
37
38 void *item = addon_cache_item( cache, head );
39 addon_cache_node *node = addon_cache_nodeptr( cache, item );
40
41 if( cache->head == cache->tail ) cache->tail = ADDON_CACHE_NIL;
42 cache->head = node->r;
43
44 node->l = ADDON_CACHE_NIL;
45 node->r = ADDON_CACHE_NIL;
46 return item;
47 }
48
49 static void addon_cache_watch( addon_cache *cache, void *item ){
50 addon_cache_node *node = addon_cache_nodeptr( cache, item );
51
52 if( node->ref_count >= 32 )
53 vg_fatal_error( "dynamic board watch missmatch (limit is 32)\n" );
54
55 node->ref_count ++;
56 }
57
58 /* if after this no more watches, places back into the volatile list */
59 static void addon_cache_unwatch( addon_cache *cache, void *item ){
60 addon_cache_node *node = addon_cache_nodeptr( cache, item );
61
62 if( node->ref_count == 0 )
63 vg_fatal_error( "dynamic board unwatch missmatch (no watchers)\n" );
64
65 node->ref_count --;
66 if( !node->ref_count ){
67 void *item_head = addon_cache_item( cache, cache->head ),
68 *item_tail = addon_cache_item( cache, cache->tail );
69 addon_cache_node *head = addon_cache_nodeptr( cache, item_head ),
70 *tail = addon_cache_nodeptr( cache, item_tail );
71
72 u16 index = addon_item_index( cache, item );
73 if( tail ) tail->r = index;
74 node->l = cache->tail;
75 cache->tail = index;
76 if( !head ) cache->head = index;
77 }
78 }
79
80 #endif /* ADDON_CACHE_C */