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