/src/gstreamer/subprojects/glib-2.86.3/glib/deprecated/gcache.c
Line | Count | Source |
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 | | g_cache_node_new (gpointer value) |
91 | 0 | { |
92 | 0 | GCacheNode *node = g_slice_new (GCacheNode); |
93 | 0 | node->value = value; |
94 | 0 | node->ref_count = 1; |
95 | 0 | return node; |
96 | 0 | } |
97 | | |
98 | | static inline void |
99 | | g_cache_node_destroy (GCacheNode *node) |
100 | 0 | { |
101 | 0 | g_slice_free (GCacheNode, node); |
102 | 0 | } |
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 | | 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 | 0 | { |
177 | 0 | GCache *cache; |
178 | |
|
179 | 0 | g_return_val_if_fail (value_new_func != NULL, NULL); |
180 | 0 | g_return_val_if_fail (value_destroy_func != NULL, NULL); |
181 | 0 | g_return_val_if_fail (key_dup_func != NULL, NULL); |
182 | 0 | g_return_val_if_fail (key_destroy_func != NULL, NULL); |
183 | 0 | g_return_val_if_fail (hash_key_func != NULL, NULL); |
184 | 0 | g_return_val_if_fail (hash_value_func != NULL, NULL); |
185 | 0 | g_return_val_if_fail (key_equal_func != NULL, NULL); |
186 | | |
187 | 0 | cache = g_slice_new (GCache); |
188 | 0 | cache->value_new_func = value_new_func; |
189 | 0 | cache->value_destroy_func = value_destroy_func; |
190 | 0 | cache->key_dup_func = key_dup_func; |
191 | 0 | cache->key_destroy_func = key_destroy_func; |
192 | 0 | cache->key_table = g_hash_table_new (hash_key_func, key_equal_func); |
193 | 0 | cache->value_table = g_hash_table_new (hash_value_func, NULL); |
194 | |
|
195 | 0 | return cache; |
196 | 0 | } |
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 | | g_cache_destroy (GCache *cache) |
211 | 0 | { |
212 | 0 | g_return_if_fail (cache != NULL); |
213 | | |
214 | 0 | g_hash_table_destroy (cache->key_table); |
215 | 0 | g_hash_table_destroy (cache->value_table); |
216 | 0 | g_slice_free (GCache, cache); |
217 | 0 | } |
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 | | g_cache_insert (GCache *cache, |
239 | | gpointer key) |
240 | 0 | { |
241 | 0 | GCacheNode *node; |
242 | 0 | gpointer value; |
243 | |
|
244 | 0 | g_return_val_if_fail (cache != NULL, NULL); |
245 | | |
246 | 0 | node = g_hash_table_lookup (cache->key_table, key); |
247 | 0 | if (node) |
248 | 0 | { |
249 | 0 | node->ref_count += 1; |
250 | 0 | return node->value; |
251 | 0 | } |
252 | | |
253 | 0 | key = (* cache->key_dup_func) (key); |
254 | 0 | value = (* cache->value_new_func) (key); |
255 | 0 | node = g_cache_node_new (value); |
256 | |
|
257 | 0 | g_hash_table_insert (cache->key_table, key, node); |
258 | 0 | g_hash_table_insert (cache->value_table, value, key); |
259 | |
|
260 | 0 | return node->value; |
261 | 0 | } |
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 | | g_cache_remove (GCache *cache, |
276 | | gconstpointer value) |
277 | 0 | { |
278 | 0 | GCacheNode *node; |
279 | 0 | gpointer key; |
280 | |
|
281 | 0 | g_return_if_fail (cache != NULL); |
282 | | |
283 | 0 | key = g_hash_table_lookup (cache->value_table, value); |
284 | 0 | node = g_hash_table_lookup (cache->key_table, key); |
285 | |
|
286 | 0 | g_return_if_fail (node != NULL); |
287 | | |
288 | 0 | node->ref_count -= 1; |
289 | 0 | if (node->ref_count == 0) |
290 | 0 | { |
291 | 0 | g_hash_table_remove (cache->value_table, value); |
292 | 0 | g_hash_table_remove (cache->key_table, key); |
293 | |
|
294 | 0 | (* cache->key_destroy_func) (key); |
295 | 0 | (* cache->value_destroy_func) (node->value); |
296 | 0 | g_cache_node_destroy (node); |
297 | 0 | } |
298 | 0 | } |
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 | | g_cache_key_foreach (GCache *cache, |
317 | | GHFunc func, |
318 | | gpointer user_data) |
319 | 0 | { |
320 | 0 | g_return_if_fail (cache != NULL); |
321 | 0 | g_return_if_fail (func != NULL); |
322 | | |
323 | 0 | g_hash_table_foreach (cache->value_table, func, user_data); |
324 | 0 | } |
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 | | g_cache_value_foreach (GCache *cache, |
339 | | GHFunc func, |
340 | | gpointer user_data) |
341 | 0 | { |
342 | 0 | g_return_if_fail (cache != NULL); |
343 | 0 | g_return_if_fail (func != NULL); |
344 | | |
345 | 0 | g_hash_table_foreach (cache->key_table, func, user_data); |
346 | 0 | } |