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
G_DEFINE_TYPE(MyObj,my_obj,G_TYPE_OBJECT)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
my_obj_class_init(MyObjClass * class)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
nop(void)44 nop (void)
45 {
46 }
47
48 #define HANDLERS 500000
49
50 static void
test_connect_many(void)51 test_connect_many (void)
52 {
53 MyObj *o;
54 gdouble time_elapsed;
55 gint i;
56
57 o = g_object_new (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 (o);
67
68 g_test_minimized_result (time_elapsed, "connected %u handlers in %6.3f seconds", HANDLERS, time_elapsed);
69 }
70
71 static void
test_disconnect_many_ordered(void)72 test_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 (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 (o, handlers[i]);
88
89 time_elapsed = g_test_timer_elapsed ();
90
91 g_object_unref (o);
92
93 g_test_minimized_result (time_elapsed, "disconnected %u handlers in %6.3f seconds", HANDLERS, time_elapsed);
94 }
95
96 static void
test_disconnect_many_inverse(void)97 test_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 (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 (o, handlers[i]);
113
114 time_elapsed = g_test_timer_elapsed ();
115
116 g_object_unref (o);
117
118 g_test_minimized_result (time_elapsed, "disconnected %u handlers in %6.3f seconds", HANDLERS, time_elapsed);
119 }
120
121 static void
test_disconnect_many_random(void)122 test_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 (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 (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 (o, handlers[i]);
147
148 time_elapsed = g_test_timer_elapsed ();
149
150 g_object_unref (o);
151
152 g_test_minimized_result (time_elapsed, "disconnected %u handlers in %6.3f seconds", HANDLERS, time_elapsed);
153 }
154
155 static void
test_disconnect_2_signals(void)156 test_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 (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 (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 (o, handlers[i]);
186
187 time_elapsed = g_test_timer_elapsed ();
188
189 g_object_unref (o);
190
191 g_test_minimized_result (time_elapsed, "disconnected %u handlers in %6.3f seconds", HANDLERS, time_elapsed);
192 }
193
194 static void
test_disconnect_2_objects(void)195 test_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 (my_obj_get_type (), NULL);
205 o2 = g_object_new (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 (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 (objects[i], handlers[i]);
236
237 time_elapsed = g_test_timer_elapsed ();
238
239 g_object_unref (o1);
240 g_object_unref (o2);
241
242 g_test_minimized_result (time_elapsed, "disconnected %u handlers in %6.3f seconds", HANDLERS, time_elapsed);
243 }
244
245 static void
test_block_many(void)246 test_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 (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 (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 (o, handlers[i]);
271
272 for (i = HANDLERS - 1; i >= 0; i--)
273 g_signal_handler_unblock (o, handlers[i]);
274
275 time_elapsed = g_test_timer_elapsed ();
276
277 g_object_unref (o);
278
279 g_test_minimized_result (time_elapsed, "blocked and unblocked %u handlers in %6.3f seconds", HANDLERS, time_elapsed);
280 }
281
282 int
main(int argc,char * argv[])283 main (int argc, char *argv[])
284 {
285 g_test_init (&argc, &argv, NULL);
286
287 if (g_test_perf ())
288 {
289 g_test_add_func ("/signal/handler/connect-many", test_connect_many);
290 g_test_add_func ("/signal/handler/disconnect-many-ordered", test_disconnect_many_ordered);
291 g_test_add_func ("/signal/handler/disconnect-many-inverse", test_disconnect_many_inverse);
292 g_test_add_func ("/signal/handler/disconnect-many-random", test_disconnect_many_random);
293 g_test_add_func ("/signal/handler/disconnect-2-signals", test_disconnect_2_signals);
294 g_test_add_func ("/signal/handler/disconnect-2-objects", test_disconnect_2_objects);
295 g_test_add_func ("/signal/handler/block-many", test_block_many);
296 }
297
298 return g_test_run ();
299 }
300