From 6908da5a57714cf33b0c9e459fe9f9d0a6cb904b Mon Sep 17 00:00:00 2001 From: "13:34:01 Tim Janik" Date: Tue, 10 Jun 2008 11:35:46 +0000 Subject: [PATCH] added race condition tester from Michael Meeks with a couple fixes so it's 2008-06-10 13:34:01 Tim Janik * tests/threadtests.c: added race condition tester from Michael Meeks with a couple fixes so it's not triggering development warnings. From: Bug 537555 - GObject instantiation not thread safe ... svn path=/trunk/; revision=6983 --- gobject/ChangeLog | 6 ++++ gobject/tests/threadtests.c | 75 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/gobject/ChangeLog b/gobject/ChangeLog index d92a3aa..f923508 100644 --- a/gobject/ChangeLog +++ b/gobject/ChangeLog @@ -1,3 +1,9 @@ +2008-06-10 13:34:01 Tim Janik + + * tests/threadtests.c: added race condition tester from Michael Meeks + with a couple fixes so it's not triggering development warnings. From: + Bug 537555 - GObject instantiation not thread safe ... + 2008-06-10 13:15:29 Tim Janik * gtype.c (g_type_class_ref): fixed race condition where references to diff --git a/gobject/tests/threadtests.c b/gobject/tests/threadtests.c index 3b95503..eabbe05 100644 --- a/gobject/tests/threadtests.c +++ b/gobject/tests/threadtests.c @@ -109,6 +109,7 @@ G_DEFINE_TYPE_WITH_CODE (MyTester2, my_tester2, G_TYPE_OBJECT, static void my_tester2_init (MyTester2*t) {} static void my_tester2_class_init (MyTester2Class*c) { call_counter_init (c); } +static GCond *sync_cond = NULL; static GMutex *sync_mutex = NULL; static gpointer @@ -138,7 +139,6 @@ test_threaded_class_init (void) { GThread *threads[3] = { NULL, }; /* pause newly created threads */ - sync_mutex = g_mutex_new(); g_mutex_lock (sync_mutex); /* create threads */ threads[0] = g_thread_create (tester_init_thread, (gpointer) my_tester0_get_type(), TRUE, NULL); @@ -158,6 +158,75 @@ test_threaded_class_init (void) g_assert_cmpint (g_atomic_int_get (&mtsafe_call_counter), ==, unsafe_call_counter); } +typedef struct { + GObject parent; + char *name; +} PropTester; +typedef GObjectClass PropTesterClass; +G_DEFINE_TYPE (PropTester, prop_tester, G_TYPE_OBJECT); +#define PROP_NAME 1 +static void +prop_tester_init (PropTester* t) +{ + if (t->name == NULL) + ; // neds unit test framework initialization: g_test_bug ("race initializing properties"); +} +static void +prop_tester_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{} +static void +prop_tester_class_init (PropTesterClass *c) +{ + int i; + GParamSpec *param; + GObjectClass *gobject_class = G_OBJECT_CLASS (c); + + gobject_class->set_property = prop_tester_set_property; /* silence GObject checks */ + + g_mutex_lock (sync_mutex); + g_cond_signal (sync_cond); + g_mutex_unlock (sync_mutex); + + for (i = 0; i < 100; i++) /* wait a bit. */ + g_thread_yield(); + + call_counter_init (c); + param = g_param_spec_string ("name", "name_i18n", + "yet-more-wasteful-i18n", + NULL, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE | + G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | + G_PARAM_STATIC_NICK); + g_object_class_install_property (gobject_class, PROP_NAME, param); +} + +static gpointer +object_create (gpointer data) +{ + GObject *obj = g_object_new (prop_tester_get_type(), "name", "fish", NULL); + g_object_unref (obj); + return NULL; +} + +static void +test_threaded_object_init (void) +{ + GThread *creator; + g_mutex_lock (sync_mutex); + + creator = g_thread_create (object_create, NULL, TRUE, NULL); + /* really provoke the race */ + g_cond_wait (sync_cond, sync_mutex); + + object_create (NULL); + g_mutex_unlock (sync_mutex); + + g_thread_join (creator); +} + int main (int argc, char *argv[]) @@ -166,7 +235,11 @@ main (int argc, g_test_init (&argc, &argv, NULL); g_type_init (); + sync_cond = g_cond_new(); + sync_mutex = g_mutex_new(); + g_test_add_func ("/GObject/threaded-class-init", test_threaded_class_init); + g_test_add_func ("/GObject/threaded-object-init", test_threaded_object_init); return g_test_run(); } -- 2.7.4