source: trunk/third/glib2/glib/gcache.c @ 18159

Revision 18159, 5.2 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18158, which included commits to RCS files with non-trunk default branches.
Line 
1/* GLIB - Library of useful routines for C programming
2 * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
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#include "glib.h"
34
35
36typedef struct _GCacheNode  GCacheNode;
37
38struct _GCacheNode
39{
40  /* A reference counted node */
41  gpointer value;
42  gint ref_count;
43};
44
45struct _GCache
46{
47  /* Called to create a value from a key */
48  GCacheNewFunc value_new_func;
49
50  /* Called to destroy a value */
51  GCacheDestroyFunc value_destroy_func;
52
53  /* Called to duplicate a key */
54  GCacheDupFunc key_dup_func;
55
56  /* Called to destroy a key */
57  GCacheDestroyFunc key_destroy_func;
58
59  /* Associates keys with nodes */
60  GHashTable *key_table;
61
62  /* Associates nodes with keys */
63  GHashTable *value_table;
64};
65
66
67static GCacheNode* g_cache_node_new     (gpointer value);
68static void        g_cache_node_destroy (GCacheNode *node);
69
70
71static GMemChunk *node_mem_chunk = NULL;
72G_LOCK_DEFINE_STATIC (node_mem_chunk);
73
74GCache*
75g_cache_new (GCacheNewFunc      value_new_func,
76             GCacheDestroyFunc  value_destroy_func,
77             GCacheDupFunc      key_dup_func,
78             GCacheDestroyFunc  key_destroy_func,
79             GHashFunc          hash_key_func,
80             GHashFunc          hash_value_func,
81             GEqualFunc         key_equal_func)
82{
83  GCache *cache;
84
85  g_return_val_if_fail (value_new_func != NULL, NULL);
86  g_return_val_if_fail (value_destroy_func != NULL, NULL);
87  g_return_val_if_fail (key_dup_func != NULL, NULL);
88  g_return_val_if_fail (key_destroy_func != NULL, NULL);
89  g_return_val_if_fail (hash_key_func != NULL, NULL);
90  g_return_val_if_fail (hash_value_func != NULL, NULL);
91  g_return_val_if_fail (key_equal_func != NULL, NULL);
92
93  cache = g_new (GCache, 1);
94  cache->value_new_func = value_new_func;
95  cache->value_destroy_func = value_destroy_func;
96  cache->key_dup_func = key_dup_func;
97  cache->key_destroy_func = key_destroy_func;
98  cache->key_table = g_hash_table_new (hash_key_func, key_equal_func);
99  cache->value_table = g_hash_table_new (hash_value_func, NULL);
100
101  return cache;
102}
103
104void
105g_cache_destroy (GCache *cache)
106{
107  g_return_if_fail (cache != NULL);
108
109  g_hash_table_destroy (cache->key_table);
110  g_hash_table_destroy (cache->value_table);
111  g_free (cache);
112}
113
114gpointer
115g_cache_insert (GCache   *cache,
116                gpointer  key)
117{
118  GCacheNode *node;
119  gpointer value;
120
121  g_return_val_if_fail (cache != NULL, NULL);
122
123  node = g_hash_table_lookup (cache->key_table, key);
124  if (node)
125    {
126      node->ref_count += 1;
127      return node->value;
128    }
129
130  key = (* cache->key_dup_func) (key);
131  value = (* cache->value_new_func) (key);
132  node = g_cache_node_new (value);
133
134  g_hash_table_insert (cache->key_table, key, node);
135  g_hash_table_insert (cache->value_table, value, key);
136
137  return node->value;
138}
139
140void
141g_cache_remove (GCache        *cache,
142                gconstpointer  value)
143{
144  GCacheNode *node;
145  gpointer key;
146
147  g_return_if_fail (cache != NULL);
148
149  key = g_hash_table_lookup (cache->value_table, value);
150  node = g_hash_table_lookup (cache->key_table, key);
151
152  g_return_if_fail (node != NULL);
153
154  node->ref_count -= 1;
155  if (node->ref_count == 0)
156    {
157      g_hash_table_remove (cache->value_table, value);
158      g_hash_table_remove (cache->key_table, key);
159
160      (* cache->key_destroy_func) (key);
161      (* cache->value_destroy_func) (node->value);
162      g_cache_node_destroy (node);
163    }
164}
165
166void
167g_cache_key_foreach (GCache   *cache,
168                     GHFunc    func,
169                     gpointer  user_data)
170{
171  g_return_if_fail (cache != NULL);
172  g_return_if_fail (func != NULL);
173
174  g_hash_table_foreach (cache->value_table, func, user_data);
175}
176
177void
178g_cache_value_foreach (GCache   *cache,
179                       GHFunc    func,
180                       gpointer  user_data)
181{
182  g_return_if_fail (cache != NULL);
183  g_return_if_fail (func != NULL);
184
185  g_hash_table_foreach (cache->key_table, func, user_data);
186}
187
188
189static GCacheNode*
190g_cache_node_new (gpointer value)
191{
192  GCacheNode *node;
193
194  G_LOCK (node_mem_chunk);
195  if (!node_mem_chunk)
196    node_mem_chunk = g_mem_chunk_new ("cache node mem chunk", sizeof (GCacheNode),
197                                      1024, G_ALLOC_AND_FREE);
198
199  node = g_chunk_new (GCacheNode, node_mem_chunk);
200  G_UNLOCK (node_mem_chunk);
201
202  node->value = value;
203  node->ref_count = 1;
204
205  return node;
206}
207
208static void
209g_cache_node_destroy (GCacheNode *node)
210{
211  G_LOCK (node_mem_chunk);
212  g_mem_chunk_free (node_mem_chunk, node);
213  G_UNLOCK (node_mem_chunk);
214}
Note: See TracBrowser for help on using the repository browser.