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 }