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

source code of gtk/subprojects/glib/gobject/tests/signal-handler.c