Branch data Line data Source code
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
70 : 893834 : my_test_get_type (void)
71 : : {
72 : : static GType test_type = 0;
73 : :
74 : 893834 : if (!test_type) {
75 : 4 : 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 : 4 : test_type = g_type_register_static (G_TYPE_OBJECT, "GTest",
89 : : &test_info, 0);
90 : : }
91 : 893834 : return test_type;
92 : : }
93 : :
94 : : static void
95 : 4 : my_test_class_init (GTestClass * klass)
96 : : {
97 : : GObjectClass *gobject_class;
98 : :
99 : 4 : gobject_class = (GObjectClass *) klass;
100 : :
101 : 4 : parent_class = g_type_class_ref (G_TYPE_OBJECT);
102 : :
103 : 4 : gobject_class->dispose = my_test_dispose;
104 : 4 : gobject_class->set_property = my_test_set_property;
105 : 4 : gobject_class->get_property = my_test_get_property;
106 : :
107 : 4 : my_test_signals[TEST_SIGNAL1] =
108 : 4 : 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 : 4 : my_test_signals[TEST_SIGNAL2] =
112 : 4 : 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 : 4 : my_test_signals[TEST_SIGNAL3] =
116 : 4 : 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 : 4 : 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 : 4 : klass->test_signal2 = signal2_handler;
125 : 4 : klass->test_signal3 = signal3_handler;
126 : 4 : }
127 : :
128 : : static void
129 : 8 : my_test_init (GTest * test)
130 : : {
131 : 8 : g_test_message ("init %p\n", test);
132 : :
133 : 8 : test->value = 0;
134 : 8 : }
135 : :
136 : : static void
137 : 8 : my_test_dispose (GObject * object)
138 : : {
139 : : GTest *test;
140 : :
141 : 8 : test = MY_TEST (object);
142 : :
143 : 8 : g_test_message ("dispose %p!\n", test);
144 : :
145 : 8 : G_OBJECT_CLASS (parent_class)->dispose (object);
146 : 8 : }
147 : :
148 : : static void
149 : 0 : my_test_set_property (GObject * object, guint prop_id,
150 : : const GValue * value, GParamSpec * pspec)
151 : : {
152 : : GTest *test;
153 : :
154 : 0 : test = MY_TEST (object);
155 : :
156 : 0 : switch (prop_id) {
157 : 0 : case ARG_TEST_PROP:
158 : 0 : test->value = g_value_get_int (value);
159 : 0 : break;
160 : 0 : default:
161 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
162 : 0 : break;
163 : : }
164 : 0 : }
165 : :
166 : : static void
167 : 893818 : my_test_get_property (GObject * object, guint prop_id,
168 : : GValue * value, GParamSpec * pspec)
169 : : {
170 : : GTest *test;
171 : :
172 : 893818 : test = MY_TEST (object);
173 : :
174 : 893818 : switch (prop_id) {
175 : 893818 : case ARG_TEST_PROP:
176 : 893818 : g_value_set_int (value, test->value);
177 : 893818 : break;
178 : 0 : default:
179 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
180 : 0 : break;
181 : : }
182 : 893818 : }
183 : :
184 : : static void
185 : 3538361 : my_test_do_signal1 (GTest * test)
186 : : {
187 : 3538361 : g_signal_emit (G_OBJECT (test), my_test_signals[TEST_SIGNAL1], 0, 0);
188 : 3538361 : }
189 : :
190 : : static void
191 : 931862 : signal2_handler (GTest * test, gint anint)
192 : : {
193 : 931862 : }
194 : :
195 : : static void
196 : 931862 : my_test_do_signal2 (GTest * test)
197 : : {
198 : 931862 : g_signal_emit (G_OBJECT (test), my_test_signals[TEST_SIGNAL2], 0, 0);
199 : 931862 : }
200 : :
201 : : static gchar *
202 : 965583 : signal3_handler (GTest * test, gint anint)
203 : : {
204 : 965583 : return g_strdup ("test");
205 : : }
206 : :
207 : : static void
208 : 965583 : my_test_do_signal3 (GTest * test)
209 : : {
210 : : gchar *res;
211 : :
212 : 965583 : g_signal_emit (G_OBJECT (test), my_test_signals[TEST_SIGNAL3], 0, 0, &res);
213 : 965583 : g_assert (res);
214 : 965583 : g_free (res);
215 : 965583 : }
216 : :
217 : : static void
218 : 2127322 : my_test_do_prop (GTest * test)
219 : : {
220 : 2127322 : test->value = g_random_int ();
221 : 2127322 : g_object_notify (G_OBJECT (test), "test-prop");
222 : 2127322 : }
223 : :
224 : : static gpointer
225 : 8 : run_thread (GTest * test)
226 : : {
227 : 8 : gint i = 1;
228 : :
229 : 7563136 : while (!g_atomic_int_get (&stopping)) {
230 : : if (TESTNUM == 1)
231 : 3538361 : my_test_do_signal1 (test);
232 : : if (TESTNUM == 2)
233 : 931862 : my_test_do_signal2 (test);
234 : : if (TESTNUM == 3)
235 : 2127322 : my_test_do_prop (test);
236 : : if (TESTNUM == 4)
237 : 965583 : my_test_do_signal3 (test);
238 : 7563128 : if ((i++ % 10000) == 0) {
239 : 752 : g_thread_yield (); /* force context switch */
240 : : }
241 : : }
242 : :
243 : 8 : return NULL;
244 : : }
245 : :
246 : : static void
247 : 893818 : notify (GObject *object, GParamSpec *spec, gpointer user_data)
248 : : {
249 : : gint value;
250 : :
251 : 893818 : g_object_get (object, "test-prop", &value, NULL);
252 : : if (TESTNUM != 3)
253 : 682789 : g_assert_cmpint (value, ==, 0);
254 : 893818 : }
255 : :
256 : : static void
257 : 4 : test_refcount_signals (void)
258 : : {
259 : : gint i;
260 : : GTest *test1, *test2;
261 : : GArray *test_threads;
262 : 4 : const gint n_threads = 1;
263 : :
264 : 4 : test1 = g_object_new (G_TYPE_TEST, NULL);
265 : 4 : test2 = g_object_new (G_TYPE_TEST, NULL);
266 : :
267 : 4 : g_signal_connect (test1, "notify::test-prop", G_CALLBACK (notify), NULL);
268 : 4 : g_signal_connect (test1, "test-signal1", G_CALLBACK (notify), NULL);
269 : 4 : g_signal_connect (test1, "test-signal2", G_CALLBACK (notify), NULL);
270 : :
271 : 4 : test_threads = g_array_new (FALSE, FALSE, sizeof (GThread *));
272 : :
273 : 4 : stopping = FALSE;
274 : :
275 : 8 : for (i = 0; i < n_threads; i++) {
276 : : GThread *thread;
277 : :
278 : 4 : thread = g_thread_new (NULL, (GThreadFunc) run_thread, test1);
279 : 4 : g_array_append_val (test_threads, thread);
280 : :
281 : 4 : thread = g_thread_new (NULL, (GThreadFunc) run_thread, test2);
282 : 4 : g_array_append_val (test_threads, thread);
283 : : }
284 : 4 : g_usleep (5000000);
285 : :
286 : 4 : g_atomic_int_set (&stopping, TRUE);
287 : :
288 : : /* Join all threads */
289 : 12 : for (i = 0; i < 2 * n_threads; i++) {
290 : : GThread *thread;
291 : :
292 : 8 : thread = g_array_index (test_threads, GThread *, i);
293 : 8 : g_thread_join (thread);
294 : : }
295 : :
296 : 4 : g_array_free (test_threads, TRUE);
297 : 4 : g_object_unref (test1);
298 : 4 : g_object_unref (test2);
299 : 4 : }
300 : :
301 : : int
302 : 4 : main (int argc, gchar *argv[])
303 : : {
304 : 4 : g_log_set_always_fatal (G_LOG_LEVEL_WARNING |
305 : 4 : G_LOG_LEVEL_CRITICAL |
306 : 4 : g_log_set_always_fatal (G_LOG_FATAL_MASK));
307 : :
308 : 4 : g_test_init (&argc, &argv, NULL);
309 : :
310 : 4 : g_test_add_func ("/gobject/refcount/signals", test_refcount_signals);
311 : :
312 : 4 : return g_test_run ();
313 : : }
|