• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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