1 #include <unistd.h> 2 #include <glib.h> 3 #include <glib-object.h> 4 5 #define G_TYPE_TEST (my_test_get_type ()) 6 #define MY_TEST(test) (G_TYPE_CHECK_INSTANCE_CAST ((test), G_TYPE_TEST, GTest)) 7 #define MY_IS_TEST(test) (G_TYPE_CHECK_INSTANCE_TYPE ((test), G_TYPE_TEST)) 8 #define MY_TEST_CLASS(tclass) (G_TYPE_CHECK_CLASS_CAST ((tclass), G_TYPE_TEST, GTestClass)) 9 #define MY_IS_TEST_CLASS(tclass) (G_TYPE_CHECK_CLASS_TYPE ((tclass), G_TYPE_TEST)) 10 #define MY_TEST_GET_CLASS(test) (G_TYPE_INSTANCE_GET_CLASS ((test), G_TYPE_TEST, GTestClass)) 11 12 typedef struct _GTest GTest; 13 typedef struct _GTestClass GTestClass; 14 15 struct _GTest 16 { 17 GObject object; 18 }; 19 20 struct _GTestClass 21 { 22 GObjectClass parent_class; 23 }; 24 25 static GType my_test_get_type (void); 26 static volatile gboolean stopping; 27 28 static void my_test_class_init (GTestClass * klass); 29 static void my_test_init (GTest * test); 30 static void my_test_dispose (GObject * object); 31 32 static GObjectClass *parent_class = NULL; 33 34 static GType 35 my_test_get_type (void) 36 { 37 static GType test_type = 0; 38 39 if (!test_type) { 40 static const GTypeInfo test_info = { 41 sizeof (GTestClass), 42 NULL, 43 NULL, 44 (GClassInitFunc) my_test_class_init, 45 NULL, 46 NULL, 47 sizeof (GTest), 48 0, 49 (GInstanceInitFunc) my_test_init, 50 NULL 51 }; 52 53 test_type = g_type_register_static (G_TYPE_OBJECT, "GTest", 54 &test_info, 0); 55 } 56 return test_type; 57 } 58 59 static void 60 my_test_class_init (GTestClass * klass) 61 { 62 GObjectClass *gobject_class; 63 64 gobject_class = (GObjectClass *) klass; 65 66 parent_class = g_type_class_ref (G_TYPE_OBJECT); 67 68 gobject_class->dispose = my_test_dispose; 69 } 70 71 static void 72 my_test_init (GTest * test) 73 { 74 g_print ("init %p\n", test); 75 } 76 77 static void 78 my_test_dispose (GObject * object) 79 { 80 GTest *test; 81 82 test = MY_TEST (object); 83 84 g_print ("dispose %p!\n", object); 85 86 G_OBJECT_CLASS (parent_class)->dispose (object); 87 } 88 89 static void 90 my_test_do_refcount (GTest * test) 91 { 92 g_object_ref (test); 93 g_object_unref (test); 94 } 95 96 static gpointer 97 run_thread (GTest * test) 98 { 99 gint i = 1; 100 101 while (!stopping) { 102 my_test_do_refcount (test); 103 if ((i++ % 10000) == 0) { 104 g_print ("."); 105 g_thread_yield(); /* force context switch */ 106 } 107 } 108 109 return NULL; 110 } 111 112 int 113 main (int argc, char **argv) 114 { 115 gint i; 116 GTest *test1, *test2; 117 GArray *test_threads; 118 const guint n_threads = 5; 119 120 g_thread_init (NULL); 121 g_print ("START: %s\n", argv[0]); 122 g_log_set_always_fatal (G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL | g_log_set_always_fatal (G_LOG_FATAL_MASK)); 123 g_type_init (); 124 125 test1 = g_object_new (G_TYPE_TEST, NULL); 126 test2 = g_object_new (G_TYPE_TEST, NULL); 127 128 test_threads = g_array_new (FALSE, FALSE, sizeof (GThread *)); 129 130 stopping = FALSE; 131 132 for (i = 0; i < n_threads; i++) { 133 GThread *thread; 134 135 thread = g_thread_create ((GThreadFunc) run_thread, test1, TRUE, NULL); 136 g_array_append_val (test_threads, thread); 137 138 thread = g_thread_create ((GThreadFunc) run_thread, test2, TRUE, NULL); 139 g_array_append_val (test_threads, thread); 140 } 141 g_usleep (5000000); 142 143 stopping = TRUE; 144 145 g_print ("\nstopping\n"); 146 147 /* join all threads */ 148 for (i = 0; i < 2 * n_threads; i++) { 149 GThread *thread; 150 151 thread = g_array_index (test_threads, GThread *, i); 152 g_thread_join (thread); 153 } 154 155 g_print ("stopped\n"); 156 157 return 0; 158 } 159