Branch data Line data Source code
1 : : /* GLIB - Library of useful routines for C programming
2 : : * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 : : *
4 : : * SPDX-License-Identifier: LGPL-2.1-or-later
5 : : *
6 : : * This library is free software; you can redistribute it and/or
7 : : * modify it under the terms of the GNU Lesser General Public
8 : : * License as published by the Free Software Foundation; either
9 : : * version 2.1 of the License, or (at your option) any later version.
10 : : *
11 : : * This library is distributed in the hope that it will be useful,
12 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : : * Lesser General Public License for more details.
15 : : *
16 : : * You should have received a copy of the GNU Lesser General Public
17 : : * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 : : */
19 : :
20 : : /*
21 : : * Modified by the GLib Team and others 1997-2000. See the AUTHORS
22 : : * file for a list of people on the GLib Team. See the ChangeLog
23 : : * files for a list of changes. These files are distributed with
24 : : * GLib at ftp://ftp.gtk.org/pub/gtk/.
25 : : */
26 : :
27 : : /*
28 : : * MT safe
29 : : */
30 : :
31 : : #include "config.h"
32 : :
33 : : /* we know we are deprecated here, no need for warnings */
34 : : #ifndef GLIB_DISABLE_DEPRECATION_WARNINGS
35 : : #define GLIB_DISABLE_DEPRECATION_WARNINGS
36 : : #endif
37 : :
38 : : #include "gcache.h"
39 : :
40 : : #include "gslice.h"
41 : : #include "ghash.h"
42 : : #include "gtestutils.h"
43 : :
44 : : /**
45 : : * GCache:
46 : : *
47 : : * A `GCache` allows sharing of complex data structures, in order to
48 : : * save system resources.
49 : : *
50 : : * `GCache` uses keys and values. A `GCache` key describes the properties
51 : : * of a particular resource. A `GCache` value is the actual resource.
52 : : *
53 : : * `GCache` has been marked as deprecated, since this API is rarely
54 : : * used and not very actively maintained.
55 : : *
56 : : * Deprecated:2.32: Use a #GHashTable instead
57 : : */
58 : :
59 : : typedef struct _GCacheNode GCacheNode;
60 : :
61 : : struct _GCacheNode
62 : : {
63 : : /* A reference counted node */
64 : : gpointer value;
65 : : gint ref_count;
66 : : };
67 : :
68 : : struct _GCache
69 : : {
70 : : /* Called to create a value from a key */
71 : : GCacheNewFunc value_new_func;
72 : :
73 : : /* Called to destroy a value */
74 : : GCacheDestroyFunc value_destroy_func;
75 : :
76 : : /* Called to duplicate a key */
77 : : GCacheDupFunc key_dup_func;
78 : :
79 : : /* Called to destroy a key */
80 : : GCacheDestroyFunc key_destroy_func;
81 : :
82 : : /* Associates keys with nodes */
83 : : GHashTable *key_table;
84 : :
85 : : /* Associates nodes with keys */
86 : : GHashTable *value_table;
87 : : };
88 : :
89 : : static inline GCacheNode*
90 : 2 : g_cache_node_new (gpointer value)
91 : : {
92 : 2 : GCacheNode *node = g_slice_new (GCacheNode);
93 : 2 : node->value = value;
94 : 2 : node->ref_count = 1;
95 : 2 : return node;
96 : : }
97 : :
98 : : static inline void
99 : 2 : g_cache_node_destroy (GCacheNode *node)
100 : : {
101 : 2 : g_slice_free (GCacheNode, node);
102 : 2 : }
103 : :
104 : : /**
105 : : * g_cache_new:
106 : : * @value_new_func: a function to create a new object given a key.
107 : : * This is called by g_cache_insert() if an object
108 : : * with the given key does not already exist
109 : : * @value_destroy_func: a function to destroy an object. It is called
110 : : * by g_cache_remove() when the object is no
111 : : * longer needed (i.e. its reference count drops
112 : : * to 0)
113 : : * @key_dup_func: a function to copy a key. It is called by
114 : : * g_cache_insert() if the key does not already exist in
115 : : * the #GCache
116 : : * @key_destroy_func: a function to destroy a key. It is called by
117 : : * g_cache_remove() when the object is no longer
118 : : * needed (i.e. its reference count drops to 0)
119 : : * @hash_key_func: a function to create a hash value from a key
120 : : * @hash_value_func: a function to create a hash value from a value
121 : : * @key_equal_func: a function to compare two keys. It should return
122 : : * %TRUE if the two keys are equivalent
123 : : *
124 : : * Creates a new #GCache.
125 : : *
126 : : * Returns: a new #GCache
127 : : *
128 : : * Deprecated:2.32: Use a #GHashTable instead
129 : : */
130 : :
131 : : /**
132 : : * GCacheNewFunc:
133 : : * @key: a #GCache key
134 : : *
135 : : * Specifies the type of the @value_new_func function passed to
136 : : * g_cache_new(). It is passed a #GCache key and should create the
137 : : * value corresponding to the key.
138 : : *
139 : : * Returns: a new #GCache value corresponding to the key.
140 : : * Deprecated:2.32: Use a #GHashTable instead
141 : : */
142 : :
143 : : /**
144 : : * GCacheDestroyFunc:
145 : : * @value: the #GCache value to destroy
146 : : *
147 : : * Specifies the type of the @value_destroy_func and @key_destroy_func
148 : : * functions passed to g_cache_new(). The functions are passed a
149 : : * pointer to the #GCache key or #GCache value and should free any
150 : : * memory and other resources associated with it.
151 : : *
152 : : * Deprecated:2.32: Use a #GHashTable instead
153 : : */
154 : :
155 : : /**
156 : : * GCacheDupFunc:
157 : : * @value: the #GCache key to destroy (__not__ a
158 : : * #GCache value as it seems)
159 : : *
160 : : * Specifies the type of the @key_dup_func function passed to
161 : : * g_cache_new(). The function is passed a key
162 : : * (__not__ a value as the prototype implies) and
163 : : * should return a duplicate of the key.
164 : : *
165 : : * Returns: a copy of the #GCache key
166 : : * Deprecated:2.32: Use a #GHashTable instead
167 : : */
168 : : GCache*
169 : 1 : g_cache_new (GCacheNewFunc value_new_func,
170 : : GCacheDestroyFunc value_destroy_func,
171 : : GCacheDupFunc key_dup_func,
172 : : GCacheDestroyFunc key_destroy_func,
173 : : GHashFunc hash_key_func,
174 : : GHashFunc hash_value_func,
175 : : GEqualFunc key_equal_func)
176 : : {
177 : : GCache *cache;
178 : :
179 : 1 : g_return_val_if_fail (value_new_func != NULL, NULL);
180 : 1 : g_return_val_if_fail (value_destroy_func != NULL, NULL);
181 : 1 : g_return_val_if_fail (key_dup_func != NULL, NULL);
182 : 1 : g_return_val_if_fail (key_destroy_func != NULL, NULL);
183 : 1 : g_return_val_if_fail (hash_key_func != NULL, NULL);
184 : 1 : g_return_val_if_fail (hash_value_func != NULL, NULL);
185 : 1 : g_return_val_if_fail (key_equal_func != NULL, NULL);
186 : :
187 : 1 : cache = g_slice_new (GCache);
188 : 1 : cache->value_new_func = value_new_func;
189 : 1 : cache->value_destroy_func = value_destroy_func;
190 : 1 : cache->key_dup_func = key_dup_func;
191 : 1 : cache->key_destroy_func = key_destroy_func;
192 : 1 : cache->key_table = g_hash_table_new (hash_key_func, key_equal_func);
193 : 1 : cache->value_table = g_hash_table_new (hash_value_func, NULL);
194 : :
195 : 1 : return cache;
196 : : }
197 : :
198 : : /**
199 : : * g_cache_destroy:
200 : : * @cache: a #GCache
201 : : *
202 : : * Frees the memory allocated for the #GCache.
203 : : *
204 : : * Note that it does not destroy the keys and values which were
205 : : * contained in the #GCache.
206 : : *
207 : : * Deprecated:2.32: Use a #GHashTable instead
208 : : */
209 : : void
210 : 1 : g_cache_destroy (GCache *cache)
211 : : {
212 : 1 : g_return_if_fail (cache != NULL);
213 : :
214 : 1 : g_hash_table_destroy (cache->key_table);
215 : 1 : g_hash_table_destroy (cache->value_table);
216 : 1 : g_slice_free (GCache, cache);
217 : : }
218 : :
219 : : /**
220 : : * g_cache_insert:
221 : : * @cache: a #GCache
222 : : * @key: a key describing a #GCache object
223 : : *
224 : : * Gets the value corresponding to the given key, creating it if
225 : : * necessary. It first checks if the value already exists in the
226 : : * #GCache, by using the @key_equal_func function passed to
227 : : * g_cache_new(). If it does already exist it is returned, and its
228 : : * reference count is increased by one. If the value does not currently
229 : : * exist, if is created by calling the @value_new_func. The key is
230 : : * duplicated by calling @key_dup_func and the duplicated key and value
231 : : * are inserted into the #GCache.
232 : : *
233 : : * Returns: a pointer to a #GCache value
234 : : *
235 : : * Deprecated:2.32: Use a #GHashTable instead
236 : : */
237 : : gpointer
238 : 3 : g_cache_insert (GCache *cache,
239 : : gpointer key)
240 : : {
241 : : GCacheNode *node;
242 : : gpointer value;
243 : :
244 : 3 : g_return_val_if_fail (cache != NULL, NULL);
245 : :
246 : 3 : node = g_hash_table_lookup (cache->key_table, key);
247 [ + + ]: 3 : if (node)
248 : : {
249 : 1 : node->ref_count += 1;
250 : 1 : return node->value;
251 : : }
252 : :
253 : 2 : key = (* cache->key_dup_func) (key);
254 : 2 : value = (* cache->value_new_func) (key);
255 : 2 : node = g_cache_node_new (value);
256 : :
257 : 2 : g_hash_table_insert (cache->key_table, key, node);
258 : 2 : g_hash_table_insert (cache->value_table, value, key);
259 : :
260 : 2 : return node->value;
261 : : }
262 : :
263 : : /**
264 : : * g_cache_remove:
265 : : * @cache: a #GCache
266 : : * @value: the value to remove
267 : : *
268 : : * Decreases the reference count of the given value. If it drops to 0
269 : : * then the value and its corresponding key are destroyed, using the
270 : : * @value_destroy_func and @key_destroy_func passed to g_cache_new().
271 : : *
272 : : * Deprecated:2.32: Use a #GHashTable instead
273 : : */
274 : : void
275 : 3 : g_cache_remove (GCache *cache,
276 : : gconstpointer value)
277 : : {
278 : : GCacheNode *node;
279 : : gpointer key;
280 : :
281 : 3 : g_return_if_fail (cache != NULL);
282 : :
283 : 3 : key = g_hash_table_lookup (cache->value_table, value);
284 : 3 : node = g_hash_table_lookup (cache->key_table, key);
285 : :
286 : 3 : g_return_if_fail (node != NULL);
287 : :
288 : 3 : node->ref_count -= 1;
289 [ + + ]: 3 : if (node->ref_count == 0)
290 : : {
291 : 2 : g_hash_table_remove (cache->value_table, value);
292 : 2 : g_hash_table_remove (cache->key_table, key);
293 : :
294 : 2 : (* cache->key_destroy_func) (key);
295 : 2 : (* cache->value_destroy_func) (node->value);
296 : 2 : g_cache_node_destroy (node);
297 : : }
298 : : }
299 : :
300 : : /**
301 : : * g_cache_key_foreach:
302 : : * @cache: a #GCache
303 : : * @func: (scope call): the function to call with each #GCache key
304 : : * @user_data: user data to pass to the function
305 : : *
306 : : * Calls the given function for each of the keys in the #GCache.
307 : : *
308 : : * NOTE @func is passed three parameters, the value and key of a cache
309 : : * entry and the @user_data. The order of value and key is different
310 : : * from the order in which g_hash_table_foreach() passes key-value
311 : : * pairs to its callback function !
312 : : *
313 : : * Deprecated:2.32: Use a #GHashTable instead
314 : : */
315 : : void
316 : 1 : g_cache_key_foreach (GCache *cache,
317 : : GHFunc func,
318 : : gpointer user_data)
319 : : {
320 : 1 : g_return_if_fail (cache != NULL);
321 : 1 : g_return_if_fail (func != NULL);
322 : :
323 : 1 : g_hash_table_foreach (cache->value_table, func, user_data);
324 : : }
325 : :
326 : : /**
327 : : * g_cache_value_foreach:
328 : : * @cache: a #GCache
329 : : * @func: (scope call): the function to call with each #GCache value
330 : : * @user_data: user data to pass to the function
331 : : *
332 : : * Calls the given function for each of the values in the #GCache.
333 : : *
334 : : * Deprecated:2.10: The reason is that it passes pointers to internal
335 : : * data structures to @func; use g_cache_key_foreach() instead
336 : : */
337 : : void
338 : 1 : g_cache_value_foreach (GCache *cache,
339 : : GHFunc func,
340 : : gpointer user_data)
341 : : {
342 : 1 : g_return_if_fail (cache != NULL);
343 : 1 : g_return_if_fail (func != NULL);
344 : :
345 : 1 : g_hash_table_foreach (cache->key_table, func, user_data);
346 : : }
|