1 #include <glib-object.h>
2
3 typedef struct {
4 GObject instance;
5 } MyObj;
6
7 typedef struct {
8 GObjectClass parent_class;
9 } MyObjClass;
10
11 enum {
12 SIGNAL1,
13 SIGNAL2,
14 LAST_SIGNAL
15 };
16
17 guint signals[LAST_SIGNAL];
18
19 GType my_obj_get_type (void);
20
21 G_DEFINE_TYPE (MyObj, my_obj, G_TYPE_OBJECT)
22
23 static void
24 my_obj_init (MyObj *o)
25 {
26 }
27
28 static void
29 my_obj_class_init (MyObjClass *class)
30 {
31 signals[SIGNAL1] =
32 g_signal_new ("signal1",
33 G_TYPE_FROM_CLASS (class),
34 G_SIGNAL_RUN_LAST,
35 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
36 signals[SIGNAL2] =
37 g_signal_new ("signal2",
38 G_TYPE_FROM_CLASS (class),
39 G_SIGNAL_RUN_LAST,
40 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
41 }
42
43 static void
44 nop (void)
45 {
46 }
47
48 static guint n_handlers = 0;
49
50 static void
51 test_connect_many (void)
52 {
53 MyObj *o;
54 gdouble time_elapsed;
55 guint i;
56
57 o = g_object_new (my_obj_get_type (), NULL);
58
59 g_test_timer_start ();
60
61 for (i = 0; i < n_handlers; i++)
62 g_signal_connect (o, "signal1", G_CALLBACK (nop), NULL);
63
64 time_elapsed = g_test_timer_elapsed ();
65
66 g_object_unref (o);
67
68 g_test_minimized_result (time_elapsed, "connected %u handlers in %6.3f seconds", n_handlers, time_elapsed);
69 }
70
71 static void
72 test_disconnect_many_ordered (void)
73 {
74 MyObj *o;
75 gulong *handlers;
76 gdouble time_elapsed;
77 guint i;
78
79 handlers = g_malloc_n (n_handlers, sizeof (*handlers));
80 o = g_object_new (my_obj_get_type (), NULL);
81
82 for (i = 0; i < n_handlers; i++)
83 handlers[i] = g_signal_connect (o, "signal1", G_CALLBACK (nop), NULL);
84
85 g_test_timer_start ();
86
87 for (i = 0; i < n_handlers; i++)
88 g_signal_handler_disconnect (o, handlers[i]);
89
90 time_elapsed = g_test_timer_elapsed ();
91
92 g_object_unref (o);
93 g_free (handlers);
94
95 g_test_minimized_result (time_elapsed, "disconnected %u handlers in %6.3f seconds", n_handlers, time_elapsed);
96 }
97
98 static void
99 test_disconnect_many_inverse (void)
100 {
101 MyObj *o;
102 gulong *handlers;
103 gdouble time_elapsed;
104 guint i;
105
106 handlers = g_malloc_n (n_handlers, sizeof (*handlers));
107 o = g_object_new (my_obj_get_type (), NULL);
108
109 for (i = 0; i < n_handlers; i++)
110 handlers[i] = g_signal_connect (o, "signal1", G_CALLBACK (nop), NULL);
111
112 g_test_timer_start ();
113
114 for (i = n_handlers; i > 0; i--)
115 g_signal_handler_disconnect (o, handlers[i - 1]);
116
117 time_elapsed = g_test_timer_elapsed ();
118
119 g_object_unref (o);
120 g_free (handlers);
121
122 g_test_minimized_result (time_elapsed, "disconnected %u handlers in %6.3f seconds", n_handlers, time_elapsed);
123 }
124
125 static void
126 test_disconnect_many_random (void)
127 {
128 MyObj *o;
129 gulong *handlers;
130 gulong id;
131 gdouble time_elapsed;
132 guint i, j;
133
134 handlers = g_malloc_n (n_handlers, sizeof (*handlers));
135 o = g_object_new (my_obj_get_type (), NULL);
136
137 for (i = 0; i < n_handlers; i++)
138 handlers[i] = g_signal_connect (o, "signal1", G_CALLBACK (nop), NULL);
139
140 for (i = 0; i < n_handlers; i++)
141 {
142 j = g_test_rand_int_range (0, n_handlers);
143 id = handlers[i];
144 handlers[i] = handlers[j];
145 handlers[j] = id;
146 }
147
148 g_test_timer_start ();
149
150 for (i = 0; i < n_handlers; i++)
151 g_signal_handler_disconnect (o, handlers[i]);
152
153 time_elapsed = g_test_timer_elapsed ();
154
155 g_object_unref (o);
156 g_free (handlers);
157
158 g_test_minimized_result (time_elapsed, "disconnected %u handlers in %6.3f seconds", n_handlers, time_elapsed);
159 }
160
161 static void
162 test_disconnect_2_signals (void)
163 {
164 MyObj *o;
165 gulong *handlers;
166 gulong id;
167 gdouble time_elapsed;
168 guint i, j;
169
170 handlers = g_malloc_n (n_handlers, sizeof (*handlers));
171 o = g_object_new (my_obj_get_type (), NULL);
172
173 for (i = 0; i < n_handlers; i++)
174 {
175 if (i % 2 == 0)
176 handlers[i] = g_signal_connect (o, "signal1", G_CALLBACK (nop), NULL);
177 else
178 handlers[i] = g_signal_connect (o, "signal2", G_CALLBACK (nop), NULL);
179 }
180
181 for (i = 0; i < n_handlers; i++)
182 {
183 j = g_test_rand_int_range (0, n_handlers);
184 id = handlers[i];
185 handlers[i] = handlers[j];
186 handlers[j] = id;
187 }
188
189 g_test_timer_start ();
190
191 for (i = 0; i < n_handlers; i++)
192 g_signal_handler_disconnect (o, handlers[i]);
193
194 time_elapsed = g_test_timer_elapsed ();
195
196 g_object_unref (o);
197 g_free (handlers);
198
199 g_test_minimized_result (time_elapsed, "disconnected %u handlers in %6.3f seconds", n_handlers, time_elapsed);
200 }
201
202 static void
203 test_disconnect_2_objects (void)
204 {
205 MyObj *o1, *o2, *o;
206 gulong *handlers;
207 MyObj **objects;
208 gulong id;
209 gdouble time_elapsed;
210 guint i, j;
211
212 handlers = g_malloc_n (n_handlers, sizeof (*handlers));
213 objects = g_malloc_n (n_handlers, sizeof (*objects));
214 o1 = g_object_new (my_obj_get_type (), NULL);
215 o2 = g_object_new (my_obj_get_type (), NULL);
216
217 for (i = 0; i < n_handlers; i++)
218 {
219 if (i % 2 == 0)
220 {
221 handlers[i] = g_signal_connect (o1, "signal1", G_CALLBACK (nop), NULL);
222 objects[i] = o1;
223 }
224 else
225 {
226 handlers[i] = g_signal_connect (o2, "signal1", G_CALLBACK (nop), NULL);
227 objects[i] = o2;
228 }
229 }
230
231 for (i = 0; i < n_handlers; i++)
232 {
233 j = g_test_rand_int_range (0, n_handlers);
234 id = handlers[i];
235 handlers[i] = handlers[j];
236 handlers[j] = id;
237 o = objects[i];
238 objects[i] = objects[j];
239 objects[j] = o;
240 }
241
242 g_test_timer_start ();
243
244 for (i = 0; i < n_handlers; i++)
245 g_signal_handler_disconnect (objects[i], handlers[i]);
246
247 time_elapsed = g_test_timer_elapsed ();
248
249 g_object_unref (o1);
250 g_object_unref (o2);
251 g_free (objects);
252 g_free (handlers);
253
254 g_test_minimized_result (time_elapsed, "disconnected %u handlers in %6.3f seconds", n_handlers, time_elapsed);
255 }
256
257 static void
258 test_block_many (void)
259 {
260 MyObj *o;
261 gulong *handlers;
262 gulong id;
263 gdouble time_elapsed;
264 guint i, j;
265
266 handlers = g_malloc_n (n_handlers, sizeof (*handlers));
267 o = g_object_new (my_obj_get_type (), NULL);
268
269 for (i = 0; i < n_handlers; i++)
270 handlers[i] = g_signal_connect (o, "signal1", G_CALLBACK (nop), NULL);
271
272 for (i = 0; i < n_handlers; i++)
273 {
274 j = g_test_rand_int_range (0, n_handlers);
275 id = handlers[i];
276 handlers[i] = handlers[j];
277 handlers[j] = id;
278 }
279
280 g_test_timer_start ();
281
282 for (i = 0; i < n_handlers; i++)
283 g_signal_handler_block (o, handlers[i]);
284
285 for (i = n_handlers; i > 0; i--)
286 g_signal_handler_unblock (o, handlers[i - 1]);
287
288 time_elapsed = g_test_timer_elapsed ();
289
290 g_object_unref (o);
291 g_free (handlers);
292
293 g_test_minimized_result (time_elapsed, "blocked and unblocked %u handlers in %6.3f seconds", n_handlers, time_elapsed);
294 }
295
296 int
297 main (int argc, char *argv[])
298 {
299 g_test_init (&argc, &argv, NULL);
300
301 n_handlers = g_test_perf () ? 500000 : 1;
302
303 g_test_add_func ("/signal/handler/connect-many", test_connect_many);
304 g_test_add_func ("/signal/handler/disconnect-many-ordered", test_disconnect_many_ordered);
305 g_test_add_func ("/signal/handler/disconnect-many-inverse", test_disconnect_many_inverse);
306 g_test_add_func ("/signal/handler/disconnect-many-random", test_disconnect_many_random);
307 g_test_add_func ("/signal/handler/disconnect-2-signals", test_disconnect_2_signals);
308 g_test_add_func ("/signal/handler/disconnect-2-objects", test_disconnect_2_objects);
309 g_test_add_func ("/signal/handler/block-many", test_block_many);
310
311 return g_test_run ();
312 }