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 static GRand *rand; 13 14 typedef struct _GTest GTest; 15 typedef struct _GTestClass GTestClass; 16 17 struct _GTest 18 { 19 GObject object; 20 21 gint value; 22 }; 23 24 struct _GTestClass 25 { 26 GObjectClass parent_class; 27 28 void (*test_signal1) (GTest * test, gint an_int); 29 void (*test_signal2) (GTest * test, gint an_int); 30 }; 31 32 static GType my_test_get_type (void); 33 static volatile gboolean stopping; 34 35 /* Element signals and args */ 36 enum 37 { 38 TEST_SIGNAL1, 39 TEST_SIGNAL2, 40 /* add more above */ 41 LAST_SIGNAL 42 }; 43 44 enum 45 { 46 ARG_0, 47 ARG_TEST_PROP 48 }; 49 50 static void my_test_class_init (GTestClass * klass); 51 static void my_test_init (GTest * test); 52 static void my_test_dispose (GObject * object); 53 54 static void signal2_handler (GTest * test, gint anint); 55 56 static void my_test_set_property (GObject * object, guint prop_id, 57 const GValue * value, GParamSpec * pspec); 58 static void my_test_get_property (GObject * object, guint prop_id, 59 GValue * value, GParamSpec * pspec); 60 61 static GObjectClass *parent_class = NULL; 62 63 static guint my_test_signals[LAST_SIGNAL] = { 0 }; 64 65 static GType 66 my_test_get_type (void) 67 { 68 static GType test_type = 0; 69 70 if (!test_type) { 71 static const GTypeInfo test_info = { 72 sizeof (GTestClass), 73 NULL, 74 NULL, 75 (GClassInitFunc) my_test_class_init, 76 NULL, 77 NULL, 78 sizeof (GTest), 79 0, 80 (GInstanceInitFunc) my_test_init, 81 NULL 82 }; 83 84 rand = g_rand_new(); 85 86 test_type = g_type_register_static (G_TYPE_OBJECT, "GTest", 87 &test_info, 0); 88 } 89 return test_type; 90 } 91 92 static void 93 my_test_class_init (GTestClass * klass) 94 { 95 GObjectClass *gobject_class; 96 97 gobject_class = (GObjectClass *) klass; 98 99 parent_class = g_type_class_ref (G_TYPE_OBJECT); 100 101 if (!g_thread_supported ()) 102 g_thread_init (NULL); 103 104 gobject_class->dispose = my_test_dispose; 105 gobject_class->set_property = my_test_set_property; 106 gobject_class->get_property = my_test_get_property; 107 108 my_test_signals[TEST_SIGNAL1] = 109 g_signal_new ("test-signal1", G_TYPE_FROM_CLASS (klass), 110 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GTestClass, test_signal1), NULL, 111 NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); 112 my_test_signals[TEST_SIGNAL2] = 113 g_signal_new ("test-signal2", G_TYPE_FROM_CLASS (klass), 114 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GTestClass, test_signal2), NULL, 115 NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); 116 117 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TEST_PROP, 118 g_param_spec_int ("test-prop", "Test Prop", "Test property", 119 0, 1, 0, G_PARAM_READWRITE)); 120 121 klass->test_signal2 = signal2_handler; 122 } 123 124 static void 125 my_test_init (GTest * test) 126 { 127 g_print ("init %p\n", test); 128 129 test->value = 0; 130 } 131 132 static void 133 my_test_dispose (GObject * object) 134 { 135 GTest *test; 136 137 test = MY_TEST (object); 138 139 g_print ("dispose %p!\n", object); 140 141 G_OBJECT_CLASS (parent_class)->dispose (object); 142 } 143 144 static void 145 my_test_set_property (GObject * object, guint prop_id, 146 const GValue * value, GParamSpec * pspec) 147 { 148 GTest *test; 149 150 test = MY_TEST (object); 151 152 switch (prop_id) { 153 case ARG_TEST_PROP: 154 test->value = g_value_get_int (value); 155 break; 156 default: 157 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 158 break; 159 } 160 } 161 162 static void 163 my_test_get_property (GObject * object, guint prop_id, 164 GValue * value, GParamSpec * pspec) 165 { 166 GTest *test; 167 168 test = MY_TEST (object); 169 170 switch (prop_id) { 171 case ARG_TEST_PROP: 172 g_value_set_int (value, test->value); 173 break; 174 default: 175 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 176 break; 177 } 178 } 179 180 static void 181 my_test_do_signal1 (GTest * test) 182 { 183 g_signal_emit (G_OBJECT (test), my_test_signals[TEST_SIGNAL1], 0, 0); 184 } 185 186 static void 187 signal2_handler (GTest * test, gint anint) 188 { 189 } 190 191 static void 192 my_test_do_signal2 (GTest * test) 193 { 194 g_signal_emit (G_OBJECT (test), my_test_signals[TEST_SIGNAL2], 0, 0); 195 } 196 197 static void 198 my_test_do_prop (GTest * test) 199 { 200 test->value = g_rand_int (rand); 201 g_object_notify (G_OBJECT (test), "test-prop"); 202 } 203 204 static gpointer 205 run_thread (GTest * test) 206 { 207 gint i = 1; 208 209 while (!stopping) { 210 if (TESTNUM == 1) 211 my_test_do_signal1 (test); 212 if (TESTNUM == 2) 213 my_test_do_signal2 (test); 214 if (TESTNUM == 3) 215 my_test_do_prop (test); 216 if ((i++ % 10000) == 0) { 217 g_print ("."); 218 g_thread_yield(); /* force context switch */ 219 } 220 } 221 222 return NULL; 223 } 224 225 static void 226 notify (GObject *object, GParamSpec *spec, gpointer user_data) 227 { 228 gint value; 229 230 g_object_get (object, "test-prop", &value, NULL); 231 /*g_print ("+ %d", value);*/ 232 } 233 234 int 235 main (int argc, char **argv) 236 { 237 gint i; 238 GTest *test1, *test2; 239 GArray *test_threads; 240 const gint n_threads = 1; 241 242 g_thread_init (NULL); 243 g_print ("START: %s\n", argv[0]); 244 g_log_set_always_fatal (G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL | g_log_set_always_fatal (G_LOG_FATAL_MASK)); 245 g_type_init (); 246 247 test1 = g_object_new (G_TYPE_TEST, NULL); 248 test2 = g_object_new (G_TYPE_TEST, NULL); 249 250 g_signal_connect (test1, "notify::test-prop", G_CALLBACK (notify), NULL); 251 g_signal_connect (test1, "test-signal1", G_CALLBACK (notify), NULL); 252 g_signal_connect (test1, "test-signal2", G_CALLBACK (notify), NULL); 253 254 test_threads = g_array_new (FALSE, FALSE, sizeof (GThread *)); 255 256 stopping = FALSE; 257 258 for (i = 0; i < n_threads; i++) { 259 GThread *thread; 260 261 thread = g_thread_create ((GThreadFunc) run_thread, test1, TRUE, NULL); 262 g_array_append_val (test_threads, thread); 263 264 thread = g_thread_create ((GThreadFunc) run_thread, test2, TRUE, NULL); 265 g_array_append_val (test_threads, thread); 266 } 267 g_usleep (5000000); 268 269 stopping = TRUE; 270 271 g_print ("\nstopping\n"); 272 273 /* join all threads */ 274 for (i = 0; i < 2 * n_threads; i++) { 275 GThread *thread; 276 277 thread = g_array_index (test_threads, GThread *, i); 278 g_thread_join (thread); 279 } 280 281 g_print ("stopped\n"); 282 283 return 0; 284 } 285