00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "glib.h"
00032
00033
00034 typedef struct _GCacheNode GCacheNode;
00035 typedef struct _GRealCache GRealCache;
00036
00037 struct _GCacheNode
00038 {
00039
00040 gpointer value;
00041 gint ref_count;
00042 };
00043
00044 struct _GRealCache
00045 {
00046
00047 GCacheNewFunc value_new_func;
00048
00049
00050 GCacheDestroyFunc value_destroy_func;
00051
00052
00053 GCacheDupFunc key_dup_func;
00054
00055
00056 GCacheDestroyFunc key_destroy_func;
00057
00058
00059 GHashTable *key_table;
00060
00061
00062 GHashTable *value_table;
00063 };
00064
00065
00066 static GCacheNode* g_cache_node_new (gpointer value);
00067 static void g_cache_node_destroy (GCacheNode *node);
00068
00069
00070 static GMemChunk *node_mem_chunk = NULL;
00071 G_LOCK_DEFINE_STATIC (node_mem_chunk);
00072
00073 GCache*
00074 g_cache_new (GCacheNewFunc value_new_func,
00075 GCacheDestroyFunc value_destroy_func,
00076 GCacheDupFunc key_dup_func,
00077 GCacheDestroyFunc key_destroy_func,
00078 GHashFunc hash_key_func,
00079 GHashFunc hash_value_func,
00080 GCompareFunc key_compare_func)
00081 {
00082 GRealCache *cache;
00083
00084 g_return_val_if_fail (value_new_func != NULL, NULL);
00085 g_return_val_if_fail (value_destroy_func != NULL, NULL);
00086 g_return_val_if_fail (key_dup_func != NULL, NULL);
00087 g_return_val_if_fail (key_destroy_func != NULL, NULL);
00088 g_return_val_if_fail (hash_key_func != NULL, NULL);
00089 g_return_val_if_fail (hash_value_func != NULL, NULL);
00090 g_return_val_if_fail (key_compare_func != NULL, NULL);
00091
00092 cache = g_new (GRealCache, 1);
00093 cache->value_new_func = value_new_func;
00094 cache->value_destroy_func = value_destroy_func;
00095 cache->key_dup_func = key_dup_func;
00096 cache->key_destroy_func = key_destroy_func;
00097 cache->key_table = g_hash_table_new (hash_key_func, key_compare_func);
00098 cache->value_table = g_hash_table_new (hash_value_func, NULL);
00099
00100 return (GCache*) cache;
00101 }
00102
00103 void
00104 g_cache_destroy (GCache *cache)
00105 {
00106 GRealCache *rcache;
00107
00108 g_return_if_fail (cache != NULL);
00109
00110 rcache = (GRealCache*) cache;
00111 g_hash_table_destroy (rcache->key_table);
00112 g_hash_table_destroy (rcache->value_table);
00113 g_free (rcache);
00114 }
00115
00116 gpointer
00117 g_cache_insert (GCache *cache,
00118 gpointer key)
00119 {
00120 GRealCache *rcache;
00121 GCacheNode *node;
00122 gpointer value;
00123
00124 g_return_val_if_fail (cache != NULL, NULL);
00125
00126 rcache = (GRealCache*) cache;
00127
00128 node = g_hash_table_lookup (rcache->key_table, key);
00129 if (node)
00130 {
00131 node->ref_count += 1;
00132 return node->value;
00133 }
00134
00135 key = (* rcache->key_dup_func) (key);
00136 value = (* rcache->value_new_func) (key);
00137 node = g_cache_node_new (value);
00138
00139 g_hash_table_insert (rcache->key_table, key, node);
00140 g_hash_table_insert (rcache->value_table, value, key);
00141
00142 return node->value;
00143 }
00144
00145 void
00146 g_cache_remove (GCache *cache,
00147 gpointer value)
00148 {
00149 GRealCache *rcache;
00150 GCacheNode *node;
00151 gpointer key;
00152
00153 g_return_if_fail (cache != NULL);
00154
00155 rcache = (GRealCache*) cache;
00156
00157 key = g_hash_table_lookup (rcache->value_table, value);
00158 node = g_hash_table_lookup (rcache->key_table, key);
00159
00160 g_return_if_fail (node != NULL);
00161
00162 node->ref_count -= 1;
00163 if (node->ref_count == 0)
00164 {
00165 g_hash_table_remove (rcache->value_table, value);
00166 g_hash_table_remove (rcache->key_table, key);
00167
00168 (* rcache->key_destroy_func) (key);
00169 (* rcache->value_destroy_func) (node->value);
00170 g_cache_node_destroy (node);
00171 }
00172 }
00173
00174 void
00175 g_cache_key_foreach (GCache *cache,
00176 GHFunc func,
00177 gpointer user_data)
00178 {
00179 GRealCache *rcache;
00180
00181 g_return_if_fail (cache != NULL);
00182 g_return_if_fail (func != NULL);
00183
00184 rcache = (GRealCache*) cache;
00185
00186 g_hash_table_foreach (rcache->value_table, func, user_data);
00187 }
00188
00189 void
00190 g_cache_value_foreach (GCache *cache,
00191 GHFunc func,
00192 gpointer user_data)
00193 {
00194 GRealCache *rcache;
00195
00196 g_return_if_fail (cache != NULL);
00197 g_return_if_fail (func != NULL);
00198
00199 rcache = (GRealCache*) cache;
00200
00201 g_hash_table_foreach (rcache->key_table, func, user_data);
00202 }
00203
00204
00205 static GCacheNode*
00206 g_cache_node_new (gpointer value)
00207 {
00208 GCacheNode *node;
00209
00210 G_LOCK (node_mem_chunk);
00211 if (!node_mem_chunk)
00212 node_mem_chunk = g_mem_chunk_new ("cache node mem chunk", sizeof (GCacheNode),
00213 1024, G_ALLOC_AND_FREE);
00214
00215 node = g_chunk_new (GCacheNode, node_mem_chunk);
00216 G_UNLOCK (node_mem_chunk);
00217
00218 node->value = value;
00219 node->ref_count = 1;
00220
00221 return node;
00222 }
00223
00224 static void
00225 g_cache_node_destroy (GCacheNode *node)
00226 {
00227 G_LOCK (node_mem_chunk);
00228 g_mem_chunk_free (node_mem_chunk, node);
00229 G_UNLOCK (node_mem_chunk);
00230 }