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 (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 | |
43 | static void |
44 | nop (void) |
45 | { |
46 | } |
47 | |
48 | #define HANDLERS 500000 |
49 | |
50 | static void |
51 | test_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 | |
71 | static 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 (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 | |
96 | static 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 (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 | |
121 | static 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 (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 | |
155 | static 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 (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 | |
194 | static 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 (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 | |
245 | static 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 (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 | |
282 | int |
283 | main (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 | |