Mercurial > audlegacy
comparison src/audacious/tuple.c @ 3427:7c2e63c5a001 trunk
Add a global GStaticRWLock to Tuple handling code. This should prevent
some concurrent access cases, but not _all_ of them.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Fri, 07 Sep 2007 06:25:02 +0300 |
parents | 86dafe2300f7 |
children | 004f822505b0 890326d0898b |
comparison
equal
deleted
inserted
replaced
3425:50a88dd6b992 | 3427:7c2e63c5a001 |
---|---|
25 | 25 |
26 static mowgli_heap_t *tuple_heap = NULL; | 26 static mowgli_heap_t *tuple_heap = NULL; |
27 static mowgli_heap_t *tuple_value_heap = NULL; | 27 static mowgli_heap_t *tuple_value_heap = NULL; |
28 static mowgli_object_class_t tuple_klass; | 28 static mowgli_object_class_t tuple_klass; |
29 | 29 |
30 static GStaticRWLock tuple_rwlock = G_STATIC_RW_LOCK_INIT; | |
31 | |
32 #define TUPLE_LOCK_WRITE(XX) g_static_rw_lock_writer_lock(&tuple_rwlock) | |
33 #define TUPLE_UNLOCK_WRITE(XX) g_static_rw_lock_writer_unlock(&tuple_rwlock) | |
34 #define TUPLE_LOCK_READ(XX) g_static_rw_lock_reader_lock(&tuple_rwlock) | |
35 #define TUPLE_UNLOCK_READ(XX) g_static_rw_lock_reader_unlock(&tuple_rwlock) | |
36 | |
30 /* iterative destructor of tuple values. */ | 37 /* iterative destructor of tuple values. */ |
31 static void | 38 static void |
32 tuple_value_destroy(mowgli_dictionary_elem_t *delem, gpointer privdata) | 39 tuple_value_destroy(mowgli_dictionary_elem_t *delem, gpointer privdata) |
33 { | 40 { |
34 TupleValue *value = (TupleValue *) delem->data; | 41 TupleValue *value = (TupleValue *) delem->data; |
42 static void | 49 static void |
43 tuple_destroy(gpointer data) | 50 tuple_destroy(gpointer data) |
44 { | 51 { |
45 Tuple *tuple = (Tuple *) data; | 52 Tuple *tuple = (Tuple *) data; |
46 | 53 |
54 TUPLE_LOCK_WRITE(); | |
47 mowgli_dictionary_destroy(tuple->dict, tuple_value_destroy, NULL); | 55 mowgli_dictionary_destroy(tuple->dict, tuple_value_destroy, NULL); |
48 mowgli_heap_free(tuple_heap, tuple); | 56 mowgli_heap_free(tuple_heap, tuple); |
57 TUPLE_UNLOCK_WRITE(); | |
49 } | 58 } |
50 | 59 |
51 Tuple * | 60 Tuple * |
52 tuple_new(void) | 61 tuple_new(void) |
53 { | 62 { |
54 Tuple *tuple; | 63 Tuple *tuple; |
55 | 64 |
65 TUPLE_LOCK_WRITE(); | |
66 | |
56 if (tuple_heap == NULL) | 67 if (tuple_heap == NULL) |
57 { | 68 { |
58 tuple_heap = mowgli_heap_create(sizeof(Tuple), 256, BH_NOW); | 69 tuple_heap = mowgli_heap_create(sizeof(Tuple), 256, BH_NOW); |
59 tuple_value_heap = mowgli_heap_create(sizeof(TupleValue), 512, BH_NOW); | 70 tuple_value_heap = mowgli_heap_create(sizeof(TupleValue), 512, BH_NOW); |
60 mowgli_object_class_init(&tuple_klass, "audacious.tuple", tuple_destroy, FALSE); | 71 mowgli_object_class_init(&tuple_klass, "audacious.tuple", tuple_destroy, FALSE); |
65 tuple = mowgli_heap_alloc(tuple_heap); | 76 tuple = mowgli_heap_alloc(tuple_heap); |
66 mowgli_object_init(mowgli_object(tuple), NULL, &tuple_klass, NULL); | 77 mowgli_object_init(mowgli_object(tuple), NULL, &tuple_klass, NULL); |
67 | 78 |
68 tuple->dict = mowgli_dictionary_create(g_ascii_strcasecmp); | 79 tuple->dict = mowgli_dictionary_create(g_ascii_strcasecmp); |
69 | 80 |
81 TUPLE_UNLOCK_WRITE(); | |
82 | |
70 return tuple; | 83 return tuple; |
71 } | 84 } |
72 | 85 |
73 Tuple * | 86 Tuple * |
74 tuple_new_from_filename(const gchar *filename) | 87 tuple_new_from_filename(const gchar *filename) |
109 TupleValue *value; | 122 TupleValue *value; |
110 | 123 |
111 g_return_val_if_fail(tuple != NULL, FALSE); | 124 g_return_val_if_fail(tuple != NULL, FALSE); |
112 g_return_val_if_fail(field != NULL, FALSE); | 125 g_return_val_if_fail(field != NULL, FALSE); |
113 | 126 |
127 TUPLE_LOCK_WRITE(); | |
114 if ((value = mowgli_dictionary_delete(tuple->dict, field))) | 128 if ((value = mowgli_dictionary_delete(tuple->dict, field))) |
115 tuple_disassociate_now(value); | 129 tuple_disassociate_now(value); |
116 | 130 |
117 if (string == NULL) | 131 if (string == NULL) { |
132 TUPLE_UNLOCK_WRITE(); | |
118 return TRUE; | 133 return TRUE; |
134 } | |
119 | 135 |
120 value = mowgli_heap_alloc(tuple_value_heap); | 136 value = mowgli_heap_alloc(tuple_value_heap); |
121 value->type = TUPLE_STRING; | 137 value->type = TUPLE_STRING; |
122 value->value.string = g_strdup(string); | 138 value->value.string = g_strdup(string); |
123 | 139 |
124 mowgli_dictionary_add(tuple->dict, field, value); | 140 mowgli_dictionary_add(tuple->dict, field, value); |
125 | 141 TUPLE_UNLOCK_WRITE(); |
142 | |
126 return TRUE; | 143 return TRUE; |
127 } | 144 } |
128 | 145 |
129 gboolean | 146 gboolean |
130 tuple_associate_int(Tuple *tuple, const gchar *field, gint integer) | 147 tuple_associate_int(Tuple *tuple, const gchar *field, gint integer) |
132 TupleValue *value; | 149 TupleValue *value; |
133 | 150 |
134 g_return_val_if_fail(tuple != NULL, FALSE); | 151 g_return_val_if_fail(tuple != NULL, FALSE); |
135 g_return_val_if_fail(field != NULL, FALSE); | 152 g_return_val_if_fail(field != NULL, FALSE); |
136 | 153 |
154 TUPLE_LOCK_WRITE(); | |
137 if ((value = mowgli_dictionary_delete(tuple->dict, field))) | 155 if ((value = mowgli_dictionary_delete(tuple->dict, field))) |
138 tuple_disassociate_now(value); | 156 tuple_disassociate_now(value); |
139 | 157 |
140 value = mowgli_heap_alloc(tuple_value_heap); | 158 value = mowgli_heap_alloc(tuple_value_heap); |
141 value->type = TUPLE_INT; | 159 value->type = TUPLE_INT; |
142 value->value.integer = integer; | 160 value->value.integer = integer; |
143 | 161 |
144 mowgli_dictionary_add(tuple->dict, field, value); | 162 mowgli_dictionary_add(tuple->dict, field, value); |
145 | 163 TUPLE_UNLOCK_WRITE(); |
164 | |
146 return TRUE; | 165 return TRUE; |
147 } | 166 } |
148 | 167 |
149 void | 168 void |
150 tuple_disassociate_now(TupleValue *value) | 169 tuple_disassociate_now(TupleValue *value) |
162 | 181 |
163 g_return_if_fail(tuple != NULL); | 182 g_return_if_fail(tuple != NULL); |
164 g_return_if_fail(field != NULL); | 183 g_return_if_fail(field != NULL); |
165 | 184 |
166 /* why _delete()? because _delete() returns the dictnode's data on success */ | 185 /* why _delete()? because _delete() returns the dictnode's data on success */ |
167 if ((value = mowgli_dictionary_delete(tuple->dict, field)) == NULL) | 186 TUPLE_LOCK_WRITE(); |
187 value = mowgli_dictionary_delete(tuple->dict, field); | |
188 | |
189 if (value == NULL) { | |
190 TUPLE_UNLOCK_WRITE(); | |
168 return; | 191 return; |
192 } | |
169 | 193 |
170 tuple_disassociate_now(value); | 194 tuple_disassociate_now(value); |
195 TUPLE_UNLOCK_WRITE(); | |
171 } | 196 } |
172 | 197 |
173 TupleValueType | 198 TupleValueType |
174 tuple_get_value_type(Tuple *tuple, const gchar *field) | 199 tuple_get_value_type(Tuple *tuple, const gchar *field) |
175 { | 200 { |
176 TupleValue *value; | 201 TupleValue *value; |
177 | 202 |
178 g_return_val_if_fail(tuple != NULL, TUPLE_UNKNOWN); | 203 g_return_val_if_fail(tuple != NULL, TUPLE_UNKNOWN); |
179 g_return_val_if_fail(field != NULL, TUPLE_UNKNOWN); | 204 g_return_val_if_fail(field != NULL, TUPLE_UNKNOWN); |
180 | 205 |
181 if ((value = mowgli_dictionary_retrieve(tuple->dict, field)) == NULL) | 206 TUPLE_LOCK_READ(); |
207 value = mowgli_dictionary_retrieve(tuple->dict, field); | |
208 TUPLE_UNLOCK_READ(); | |
209 | |
210 if (value == NULL) | |
182 return TUPLE_UNKNOWN; | 211 return TUPLE_UNKNOWN; |
183 | 212 |
184 return value->type; | 213 return value->type; |
185 } | 214 } |
186 | 215 |
187 const gchar * | 216 const gchar * |
188 tuple_get_string(Tuple *tuple, const gchar *field) | 217 tuple_get_string(Tuple *tuple, const gchar *field) |
189 { | 218 { |
190 TupleValue *value; | 219 TupleValue *value; |
220 gchar *val; | |
191 | 221 |
192 g_return_val_if_fail(tuple != NULL, NULL); | 222 g_return_val_if_fail(tuple != NULL, NULL); |
193 g_return_val_if_fail(field != NULL, NULL); | 223 g_return_val_if_fail(field != NULL, NULL); |
194 | 224 |
195 if ((value = mowgli_dictionary_retrieve(tuple->dict, field)) == NULL) | 225 TUPLE_LOCK_READ(); |
226 value = mowgli_dictionary_retrieve(tuple->dict, field); | |
227 | |
228 if (value == NULL) { | |
229 TUPLE_UNLOCK_READ(); | |
196 return NULL; | 230 return NULL; |
197 | 231 } |
198 if (value->type != TUPLE_STRING) | 232 |
233 if (value->type != TUPLE_STRING) { | |
234 TUPLE_UNLOCK_READ(); | |
199 mowgli_throw_exception_val(audacious.tuple.invalid_type_request, NULL); | 235 mowgli_throw_exception_val(audacious.tuple.invalid_type_request, NULL); |
200 | 236 } |
201 return value->value.string; | 237 |
238 val = value->value.string; | |
239 TUPLE_UNLOCK_READ(); | |
240 | |
241 return val; | |
202 } | 242 } |
203 | 243 |
204 int | 244 int |
205 tuple_get_int(Tuple *tuple, const gchar *field) | 245 tuple_get_int(Tuple *tuple, const gchar *field) |
206 { | 246 { |
207 TupleValue *value; | 247 TupleValue *value; |
248 gint val; | |
208 | 249 |
209 g_return_val_if_fail(tuple != NULL, 0); | 250 g_return_val_if_fail(tuple != NULL, 0); |
210 g_return_val_if_fail(field != NULL, 0); | 251 g_return_val_if_fail(field != NULL, 0); |
211 | 252 |
212 if ((value = mowgli_dictionary_retrieve(tuple->dict, field)) == NULL) | 253 TUPLE_LOCK_READ(); |
254 value = mowgli_dictionary_retrieve(tuple->dict, field); | |
255 | |
256 if (value == NULL) { | |
257 TUPLE_UNLOCK_READ(); | |
213 return 0; | 258 return 0; |
214 | 259 } |
215 if (value->type != TUPLE_INT) | 260 |
261 if (value->type != TUPLE_INT) { | |
262 TUPLE_UNLOCK_READ(); | |
216 mowgli_throw_exception_val(audacious.tuple.invalid_type_request, 0); | 263 mowgli_throw_exception_val(audacious.tuple.invalid_type_request, 0); |
217 | 264 } |
218 return value->value.integer; | 265 |
219 } | 266 val = value->value.integer; |
267 TUPLE_UNLOCK_READ(); | |
268 | |
269 return val; | |
270 } |