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