1 /*
2 * cache.c general cache manager
3 *
4 * Copyright (C) 1997-1998 Masaki Chikama (Wren) <chikama@kasumi.ipl.mech.nagoya-u.ac.jp>
5 * 1998- <masaki-c@is.aist-nara.ac.jp>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22 /* $Id: cache.c,v 1.5 2003/07/21 23:06:47 chikama Exp $ */
23
24 #include "config.h"
25 #include <stdio.h>
26 #include <limits.h>
27 #include <glib.h>
28 #include "portab.h"
29 #include "cache.h"
30
31 /* maximum cache size (in MB) */
32 #ifndef CACHE_TOTALSIZE
33 #define CACHE_TOTALSIZE 20
34 #endif
35
36 static int totalsize; /* total size in cache */
37 static int id = 0; /* Id of cache object */
38 static boolean dummyfalse = FALSE; /* dummy in_use flag */
39 static boolean dummytrue = TRUE; /* dummy in_use flag */
40
41 /*
42 * static methods
43 */
44 static void remove_in_cache(cacher *id);
45
46 /*
47 * Remove data in cache
48 * id: cache handler
49 */
remove_in_cache(cacher * id)50 static void remove_in_cache(cacher *id) {
51 cacheinfo *ip = id->top;
52 cacheinfo *ic = ip->next;
53
54 while(ic->next != NULL) {
55 if (!(boolean)*(ic->in_use)) {
56 if (ic->refcnt-- == 0) {
57 totalsize -= ic->size;
58 if (ic->next != NULL) {
59 ip->next = ic->next;
60 } else {
61 ip->next = NULL;
62 }
63 id->free_(ic->data);
64 }
65 } else {
66 ip = ic;
67 }
68 g_free(ic);
69 ic = ip->next;
70 }
71 return;
72 }
73
74 /*
75 * Create new cache object
76 * delcallback: callback function for delete cache data object
77 * return: new cache handler
78 */
cache_new(void * delcallback)79 cacher *cache_new(void *delcallback) {
80 cacher *c = g_new0(cacher, 1);
81
82 c->id = id;
83 c->top = g_new0(cacheinfo, 1);
84 c->top->next = NULL;
85 c->top->in_use = &dummytrue;
86 c->free_ = delcallback;
87 id++;
88 return c;
89 }
90
91 /*
92 * Insert data to cache
93 * id : cache handler
94 * key : data key
95 * data : data to be cached
96 * size : data size
97 * in_use: in_use mark pointer, if in_use is TRUE, dont remove from cache
98 */
cache_insert(cacher * id,int key,void * data,int size,boolean * in_use)99 void cache_insert(cacher *id, int key, void *data, int size, boolean *in_use) {
100 cacheinfo *i = id->top;
101
102 if (CACHE_TOTALSIZE <= (totalsize >> 20)) {
103 remove_in_cache(id);
104 }
105
106 while(i->next != NULL) {
107 i = i->next;
108 }
109
110 i->key = key;
111 i->data = data;
112 i->size = size;
113 i->next = g_new0(cacheinfo, 1);
114 i->next->next = NULL;
115 if (in_use) {
116 i->in_use = in_use;
117 } else {
118 i->in_use = &dummyfalse;
119 }
120 totalsize += size;
121 }
122
123 /*
124 * Search data in cache
125 * id : cache handler
126 * key: data search key
127 * return: pointer to cached data
128 */
cache_foreach(cacher * id,int key)129 void *cache_foreach(cacher *id, int key) {
130 cacheinfo *i = id->top;
131
132 while(i != NULL) {
133 if (i->key == key) {
134 if (INT_MAX < i->refcnt) {
135 i->refcnt++;
136 }
137 return i->data;
138 }
139 i = i->next;
140 }
141 return NULL;
142 }
143