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 12typedef struct _GTest GTest; 13typedef struct _GTestClass GTestClass; 14 15struct _GTest 16{ 17 GObject object; 18}; 19 20struct _GTestClass 21{ 22 GObjectClass parent_class; 23}; 24 25static GType my_test_get_type (void); 26static volatile gboolean stopping; 27 28static void my_test_class_init (GTestClass * klass); 29static void my_test_init (GTest * test); 30static void my_test_dispose (GObject * object); 31 32static GObjectClass *parent_class = NULL; 33 34static GType 35my_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 59static void 60my_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 71static void 72my_test_init (GTest * test) 73{ 74 g_print ("init %p\n", test); 75} 76 77static void 78my_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 89static void 90my_test_do_refcount (GTest * test) 91{ 92 g_object_ref (test); 93 g_object_unref (test); 94} 95 96static gpointer 97run_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 112int 113main (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