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