+Sun Jul 31 01:50:20 2005 Tim Janik <timj@gtk.org>
+
+ * glib/gdataset.c:
+ moved G_DATALIST_*_POINTER() macros here, because proper use requires
+ the global g_dataset_global mutex to be acquired.
+ g_datalist_id_get_data():
+ g_datalist_unset_flags():
+ g_datalist_set_flags(): properly acquire and release dataset mutex.
+
+ * glib/gdatasetprivate.h: implement G_DATALIST_GET_FLAGS() via atomic
+ pointer access to account for memory barriers. moved all other macros.
+
2005-07-26 Matthias Clasen <mclasen@redhat.com>
* glib/goption.c: Include glibintl.h, not gi18n.h, noticed
+Sun Jul 31 01:50:20 2005 Tim Janik <timj@gtk.org>
+
+ * glib/gdataset.c:
+ moved G_DATALIST_*_POINTER() macros here, because proper use requires
+ the global g_dataset_global mutex to be acquired.
+ g_datalist_id_get_data():
+ g_datalist_unset_flags():
+ g_datalist_set_flags(): properly acquire and release dataset mutex.
+
+ * glib/gdatasetprivate.h: implement G_DATALIST_GET_FLAGS() via atomic
+ pointer access to account for memory barriers. moved all other macros.
+
2005-07-26 Matthias Clasen <mclasen@redhat.com>
* glib/goption.c: Include glibintl.h, not gi18n.h, noticed
+Sun Jul 31 01:50:20 2005 Tim Janik <timj@gtk.org>
+
+ * glib/gdataset.c:
+ moved G_DATALIST_*_POINTER() macros here, because proper use requires
+ the global g_dataset_global mutex to be acquired.
+ g_datalist_id_get_data():
+ g_datalist_unset_flags():
+ g_datalist_set_flags(): properly acquire and release dataset mutex.
+
+ * glib/gdatasetprivate.h: implement G_DATALIST_GET_FLAGS() via atomic
+ pointer access to account for memory barriers. moved all other macros.
+
2005-07-26 Matthias Clasen <mclasen@redhat.com>
* glib/goption.c: Include glibintl.h, not gi18n.h, noticed
+Sun Jul 31 01:50:20 2005 Tim Janik <timj@gtk.org>
+
+ * glib/gdataset.c:
+ moved G_DATALIST_*_POINTER() macros here, because proper use requires
+ the global g_dataset_global mutex to be acquired.
+ g_datalist_id_get_data():
+ g_datalist_unset_flags():
+ g_datalist_set_flags(): properly acquire and release dataset mutex.
+
+ * glib/gdatasetprivate.h: implement G_DATALIST_GET_FLAGS() via atomic
+ pointer access to account for memory barriers. moved all other macros.
+
2005-07-26 Matthias Clasen <mclasen@redhat.com>
* glib/goption.c: Include glibintl.h, not gi18n.h, noticed
*/
/*
- * MT safe ; FIXME: might still freeze, watch out, not thoroughly
- * looked at yet.
+ * MT safe ; except for g_data*_foreach()
*/
#include "config.h"
#define G_DATA_CACHE_MAX (512)
#define G_DATASET_MEM_CHUNK_PREALLOC (32)
+/* datalist pointer modifications have to be done with the g_dataset_global mutex held */
+#define G_DATALIST_GET_POINTER(datalist) \
+ ((GData*) ((gsize) *(datalist) & ~(gsize) G_DATALIST_FLAGS_MASK))
+#define G_DATALIST_SET_POINTER(datalist, pointer) G_STMT_START { \
+ *(datalist) = (GData*) (G_DATALIST_GET_FLAGS (datalist) | \
+ (gsize) pointer); \
+} G_STMT_END
+
/* --- structures --- */
typedef struct _GDataset GDataset;
g_datalist_id_get_data (GData **datalist,
GQuark key_id)
{
+ gpointer data = NULL;
g_return_val_if_fail (datalist != NULL, NULL);
-
if (key_id)
{
register GData *list;
-
+ G_LOCK (g_dataset_global);
for (list = G_DATALIST_GET_POINTER (datalist); list; list = list->next)
if (list->id == key_id)
- return list->data;
+ {
+ data = list->data;
+ break;
+ }
+ G_UNLOCK (g_dataset_global);
}
-
- return NULL;
+ return data;
}
void
g_return_if_fail (datalist != NULL);
g_return_if_fail ((flags & ~G_DATALIST_FLAGS_MASK) == 0);
- G_DATALIST_SET_FLAGS (datalist, flags);
+ G_LOCK (g_dataset_global);
+ *datalist = (GData*) (flags | (gsize) *datalist);
+ G_UNLOCK (g_dataset_global);
}
/**
g_return_if_fail (datalist != NULL);
g_return_if_fail ((flags & ~G_DATALIST_FLAGS_MASK) == 0);
- G_DATALIST_UNSET_FLAGS (datalist, flags);
+ G_LOCK (g_dataset_global);
+ *datalist = (GData*) (~(gsize) flags & (gsize) *datalist);
+ G_UNLOCK (g_dataset_global);
}
/**
{
g_return_val_if_fail (datalist != NULL, 0);
- return G_DATALIST_GET_FLAGS (datalist);
+ return G_DATALIST_GET_FLAGS (datalist); /* atomic macro */
}
/* HOLDS: g_dataset_global_lock */
G_BEGIN_DECLS
+/* GET_FLAGS is implemented via atomic pointer access, to allow memory
+ * barriers take effect without acquirering the global dataset mutex.
+ */
#define G_DATALIST_GET_FLAGS(datalist) \
- ((gsize)*(datalist) & G_DATALIST_FLAGS_MASK)
-#define G_DATALIST_SET_FLAGS(datalist, flags) G_STMT_START { \
- *datalist = (GData *)((flags) | (gsize)*(datalist)); \
-} G_STMT_END
-#define G_DATALIST_UNSET_FLAGS(datalist, flags) G_STMT_START { \
- *datalist = (GData *)(~(gsize)(flags) & (gsize)*(datalist)); \
-} G_STMT_END
-
-#define G_DATALIST_GET_POINTER(datalist) \
- ((GData *)((gsize)*(datalist) & ~(gsize)G_DATALIST_FLAGS_MASK))
-#define G_DATALIST_SET_POINTER(datalist,pointer) G_STMT_START { \
- *(datalist) = (GData *)(G_DATALIST_GET_FLAGS (datalist) | \
- (gsize)pointer); \
-} G_STMT_END
+ ((gsize) g_atomic_pointer_get (datalist) & G_DATALIST_FLAGS_MASK)
+
G_END_DECLS