Branch data Line data Source code
1 : : /* GObject - GLib Type, Object, Parameter and Signal Library
2 : : * Copyright (C) 2000-2001 Red Hat, Inc.
3 : : *
4 : : * SPDX-License-Identifier: LGPL-2.1-or-later
5 : : *
6 : : * This library is free software; you can redistribute it and/or
7 : : * modify it under the terms of the GNU Lesser General Public
8 : : * License as published by the Free Software Foundation; either
9 : : * version 2.1 of the License, or (at your option) any later version.
10 : : *
11 : : * This library is distributed in the hope that it will be useful,
12 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : : * Lesser General Public License for more details.
15 : : *
16 : : * You should have received a copy of the GNU Lesser General
17 : : * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 : : *
19 : : * this code is based on the original GtkSignal implementation
20 : : * for the Gtk+ library by Peter Mattis <petm@xcf.berkeley.edu>
21 : : */
22 : :
23 : : /*
24 : : * MT safe
25 : : */
26 : :
27 : : #include "config.h"
28 : :
29 : : #include <string.h>
30 : : #include <signal.h>
31 : :
32 : : #include "gsignal.h"
33 : : #include "gtype-private.h"
34 : : #include "gbsearcharray.h"
35 : : #include "gvaluecollector.h"
36 : : #include "gvaluetypes.h"
37 : : #include "gobject.h"
38 : : #include "genums.h"
39 : : #include "gobject_trace.h"
40 : :
41 : :
42 : : #define REPORT_BUG "please report occurrence circumstances to https://gitlab.gnome.org/GNOME/glib/issues/new"
43 : :
44 : : /* --- typedefs --- */
45 : : typedef struct _SignalNode SignalNode;
46 : : typedef struct _SignalKey SignalKey;
47 : : typedef struct _Emission Emission;
48 : : typedef struct _Handler Handler;
49 : : typedef struct _HandlerList HandlerList;
50 : : typedef struct _HandlerMatch HandlerMatch;
51 : : typedef enum
52 : : {
53 : : EMISSION_STOP,
54 : : EMISSION_RUN,
55 : : EMISSION_HOOK,
56 : : EMISSION_RESTART
57 : : } EmissionState;
58 : :
59 : :
60 : : /* --- prototypes --- */
61 : : static inline guint signal_id_lookup (const gchar *name,
62 : : GType itype);
63 : : static void signal_destroy_R (SignalNode *signal_node);
64 : : static inline HandlerList* handler_list_ensure (guint signal_id,
65 : : gpointer instance);
66 : : static inline HandlerList* handler_list_lookup (guint signal_id,
67 : : gpointer instance);
68 : : static inline Handler* handler_new (guint signal_id,
69 : : gpointer instance,
70 : : gboolean after);
71 : : static void handler_insert (guint signal_id,
72 : : gpointer instance,
73 : : Handler *handler);
74 : : static Handler* handler_lookup (gpointer instance,
75 : : gulong handler_id,
76 : : GClosure *closure,
77 : : guint *signal_id_p);
78 : : static inline HandlerMatch* handler_match_prepend (HandlerMatch *list,
79 : : Handler *handler,
80 : : guint signal_id);
81 : : static inline HandlerMatch* handler_match_free1_R (HandlerMatch *node,
82 : : gpointer instance);
83 : : static HandlerMatch* handlers_find (gpointer instance,
84 : : GSignalMatchType mask,
85 : : guint signal_id,
86 : : GQuark detail,
87 : : GClosure *closure,
88 : : gpointer func,
89 : : gpointer data,
90 : : gboolean one_and_only);
91 : : static inline void handler_ref (Handler *handler);
92 : : static inline void handler_unref_R (guint signal_id,
93 : : gpointer instance,
94 : : Handler *handler);
95 : : static gint handler_lists_cmp (gconstpointer node1,
96 : : gconstpointer node2);
97 : : static inline void emission_push (Emission *emission);
98 : : static inline void emission_pop (Emission *emission);
99 : : static inline Emission* emission_find (guint signal_id,
100 : : GQuark detail,
101 : : gpointer instance);
102 : : static gint class_closures_cmp (gconstpointer node1,
103 : : gconstpointer node2);
104 : : static gint signal_key_cmp (gconstpointer node1,
105 : : gconstpointer node2);
106 : : static gboolean signal_emit_unlocked_R (SignalNode *node,
107 : : GQuark detail,
108 : : gpointer instance,
109 : : GValue *return_value,
110 : : const GValue *instance_and_params);
111 : : static void add_invalid_closure_notify (Handler *handler,
112 : : gpointer instance);
113 : : static void remove_invalid_closure_notify (Handler *handler,
114 : : gpointer instance);
115 : : static void invalid_closure_notify (gpointer data,
116 : : GClosure *closure);
117 : : static const gchar * type_debug_name (GType type);
118 : : static void node_check_deprecated (const SignalNode *node);
119 : : static void node_update_single_va_closure (SignalNode *node);
120 : :
121 : :
122 : : /* --- structures --- */
123 : : typedef struct
124 : : {
125 : : GSignalAccumulator func;
126 : : gpointer data;
127 : : } SignalAccumulator;
128 : : typedef struct
129 : : {
130 : : GHook hook;
131 : : GQuark detail;
132 : : } SignalHook;
133 : : #define SIGNAL_HOOK(hook) ((SignalHook*) (hook))
134 : :
135 : : struct _SignalNode
136 : : {
137 : : /* permanent portion */
138 : : guint signal_id;
139 : : GType itype;
140 : : const gchar *name;
141 : : guint destroyed : 1;
142 : :
143 : : /* reinitializable portion */
144 : : guint flags : 9;
145 : : guint n_params : 8;
146 : : guint single_va_closure_is_valid : 1;
147 : : guint single_va_closure_is_after : 1;
148 : : GType *param_types; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */
149 : : GType return_type; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */
150 : : GBSearchArray *class_closure_bsa;
151 : : SignalAccumulator *accumulator;
152 : : GSignalCMarshaller c_marshaller;
153 : : GSignalCVaMarshaller va_marshaller;
154 : : GHookList *emission_hooks;
155 : :
156 : : GClosure *single_va_closure;
157 : : };
158 : :
159 : : #define SINGLE_VA_CLOSURE_EMPTY_MAGIC GINT_TO_POINTER(1) /* indicates single_va_closure is valid but empty */
160 : :
161 : : struct _SignalKey
162 : : {
163 : : GType itype;
164 : : GQuark quark;
165 : : guint signal_id;
166 : : };
167 : :
168 : : struct _Emission
169 : : {
170 : : Emission *next;
171 : : gpointer instance;
172 : : GSignalInvocationHint ihint;
173 : : EmissionState state;
174 : : GType chain_type;
175 : : };
176 : :
177 : : struct _HandlerList
178 : : {
179 : : guint signal_id;
180 : : Handler *handlers;
181 : : Handler *tail_before; /* normal signal handlers are appended here */
182 : : Handler *tail_after; /* CONNECT_AFTER handlers are appended here */
183 : : };
184 : :
185 : : struct _Handler
186 : : {
187 : : gulong sequential_number;
188 : : Handler *next;
189 : : Handler *prev;
190 : : GQuark detail;
191 : : guint signal_id;
192 : : guint ref_count;
193 : : guint block_count : 16;
194 : : #define HANDLER_MAX_BLOCK_COUNT (1 << 16)
195 : : guint after : 1;
196 : : guint has_invalid_closure_notify : 1;
197 : : GClosure *closure;
198 : : gpointer instance;
199 : : };
200 : : struct _HandlerMatch
201 : : {
202 : : Handler *handler;
203 : : HandlerMatch *next;
204 : : guint signal_id;
205 : : };
206 : :
207 : : typedef struct
208 : : {
209 : : GType instance_type; /* 0 for default closure */
210 : : GClosure *closure;
211 : : } ClassClosure;
212 : :
213 : :
214 : : /* --- variables --- */
215 : : static GBSearchArray *g_signal_key_bsa = NULL;
216 : : static const GBSearchConfig g_signal_key_bconfig = {
217 : : sizeof (SignalKey),
218 : : signal_key_cmp,
219 : : G_BSEARCH_ARRAY_ALIGN_POWER2,
220 : : };
221 : : static GBSearchConfig g_signal_hlbsa_bconfig = {
222 : : sizeof (HandlerList),
223 : : handler_lists_cmp,
224 : : 0,
225 : : };
226 : : static GBSearchConfig g_class_closure_bconfig = {
227 : : sizeof (ClassClosure),
228 : : class_closures_cmp,
229 : : 0,
230 : : };
231 : : static GHashTable *g_handler_list_bsa_ht = NULL;
232 : : static Emission *g_emissions = NULL;
233 : : static gulong g_handler_sequential_number = 1;
234 : : static GHashTable *g_handlers = NULL;
235 : :
236 : : G_LOCK_DEFINE_STATIC (g_signal_mutex);
237 : : #define SIGNAL_LOCK() G_LOCK (g_signal_mutex)
238 : : #define SIGNAL_UNLOCK() G_UNLOCK (g_signal_mutex)
239 : :
240 : :
241 : : /* --- signal nodes --- */
242 : : static guint g_n_signal_nodes = 0;
243 : : static SignalNode **g_signal_nodes = NULL;
244 : :
245 : : static inline SignalNode*
246 : 39022703 : LOOKUP_SIGNAL_NODE (guint signal_id)
247 : : {
248 [ + - ]: 39022703 : if (signal_id < g_n_signal_nodes)
249 : 39022703 : return g_signal_nodes[signal_id];
250 : : else
251 : 0 : return NULL;
252 : : }
253 : :
254 : :
255 : : /* --- functions --- */
256 : : /* @key must have already been validated with is_valid()
257 : : * Modifies @key in place. */
258 : : static void
259 : 4 : canonicalize_key (gchar *key)
260 : : {
261 : : gchar *p;
262 : :
263 [ + + ]: 49 : for (p = key; *p != 0; p++)
264 : : {
265 : 45 : gchar c = *p;
266 : :
267 [ + + ]: 45 : if (c == '_')
268 : 4 : *p = '-';
269 : : }
270 : 4 : }
271 : :
272 : : /* @key must have already been validated with is_valid() */
273 : : static gboolean
274 : 3580 : is_canonical (const gchar *key)
275 : : {
276 : 3580 : return (strchr (key, '_') == NULL);
277 : : }
278 : :
279 : : /**
280 : : * g_signal_is_valid_name:
281 : : * @name: the canonical name of the signal
282 : : *
283 : : * Validate a signal name. This can be useful for dynamically-generated signals
284 : : * which need to be validated at run-time before actually trying to create them.
285 : : *
286 : : * See [canonical parameter names][canonical-parameter-names] for details of
287 : : * the rules for valid names. The rules for signal names are the same as those
288 : : * for property names.
289 : : *
290 : : * Returns: %TRUE if @name is a valid signal name, %FALSE otherwise.
291 : : * Since: 2.66
292 : : */
293 : : gboolean
294 : 1795 : g_signal_is_valid_name (const gchar *name)
295 : : {
296 : : /* FIXME: We allow this, against our own documentation (the leading `-` is
297 : : * invalid), because GTK has historically used this. */
298 [ - + ]: 1795 : if (g_str_equal (name, "-gtk-private-changed"))
299 : 0 : return TRUE;
300 : :
301 : 1795 : return g_param_spec_is_valid_name (name);
302 : : }
303 : :
304 : : static inline guint
305 : 544032 : signal_id_lookup (const gchar *name,
306 : : GType itype)
307 : : {
308 : : GQuark quark;
309 : 544032 : GType *ifaces, type = itype;
310 : : SignalKey key;
311 : : guint n_ifaces;
312 : :
313 : 544032 : quark = g_quark_try_string (name);
314 : 544032 : key.quark = quark;
315 : :
316 : : /* try looking up signals for this type and its ancestors */
317 : : do
318 : : {
319 : : SignalKey *signal_key;
320 : :
321 : 952033 : key.itype = type;
322 : 952033 : signal_key = g_bsearch_array_lookup (g_signal_key_bsa, &g_signal_key_bconfig, &key);
323 : :
324 [ + + ]: 952033 : if (signal_key)
325 : 141646 : return signal_key->signal_id;
326 : :
327 : 810387 : type = g_type_parent (type);
328 : : }
329 [ + + ]: 810387 : while (type);
330 : :
331 : : /* no luck, try interfaces it exports */
332 : 402386 : ifaces = g_type_interfaces (itype, &n_ifaces);
333 [ + + ]: 804394 : while (n_ifaces--)
334 : : {
335 : : SignalKey *signal_key;
336 : :
337 : 802600 : key.itype = ifaces[n_ifaces];
338 : 802600 : signal_key = g_bsearch_array_lookup (g_signal_key_bsa, &g_signal_key_bconfig, &key);
339 : :
340 [ + + ]: 802600 : if (signal_key)
341 : : {
342 : 400592 : g_free (ifaces);
343 : 400592 : return signal_key->signal_id;
344 : : }
345 : : }
346 : 1794 : g_free (ifaces);
347 : :
348 : : /* If the @name is non-canonical, try again. This is the slow path — people
349 : : * should use canonical names in their queries if they want performance. */
350 [ + + ]: 1794 : if (!is_canonical (name))
351 : : {
352 : : guint signal_id;
353 : 3 : gchar *name_copy = g_strdup (name);
354 : 3 : canonicalize_key (name_copy);
355 : :
356 : 3 : signal_id = signal_id_lookup (name_copy, itype);
357 : :
358 : 3 : g_free (name_copy);
359 : :
360 : 3 : return signal_id;
361 : : }
362 : :
363 : 1791 : return 0;
364 : : }
365 : :
366 : : static gint
367 : 90 : class_closures_cmp (gconstpointer node1,
368 : : gconstpointer node2)
369 : : {
370 : 90 : const ClassClosure *c1 = node1, *c2 = node2;
371 : :
372 [ + + + + ]: 90 : return G_BSEARCH_ARRAY_CMP (c1->instance_type, c2->instance_type);
373 : : }
374 : :
375 : : static gint
376 : 38211368 : handler_lists_cmp (gconstpointer node1,
377 : : gconstpointer node2)
378 : : {
379 : 38211368 : const HandlerList *hlist1 = node1, *hlist2 = node2;
380 : :
381 [ + + + + ]: 38211368 : return G_BSEARCH_ARRAY_CMP (hlist1->signal_id, hlist2->signal_id);
382 : : }
383 : :
384 : : static inline HandlerList*
385 : 539760 : handler_list_ensure (guint signal_id,
386 : : gpointer instance)
387 : : {
388 : 539760 : GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
389 : : HandlerList key;
390 : :
391 : 539760 : key.signal_id = signal_id;
392 : 539760 : key.handlers = NULL;
393 : 539760 : key.tail_before = NULL;
394 : 539760 : key.tail_after = NULL;
395 [ + + ]: 539760 : if (!hlbsa)
396 : : {
397 : 107030 : hlbsa = g_bsearch_array_create (&g_signal_hlbsa_bconfig);
398 : : }
399 : 539760 : hlbsa = g_bsearch_array_insert (hlbsa, &g_signal_hlbsa_bconfig, &key);
400 : 539760 : g_hash_table_insert (g_handler_list_bsa_ht, instance, hlbsa);
401 : 539760 : return g_bsearch_array_lookup (hlbsa, &g_signal_hlbsa_bconfig, &key);
402 : : }
403 : :
404 : : static inline HandlerList*
405 : 29501552 : handler_list_lookup (guint signal_id,
406 : : gpointer instance)
407 : : {
408 : 29501552 : GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
409 : : HandlerList key;
410 : :
411 : 29501552 : key.signal_id = signal_id;
412 : :
413 [ + + ]: 29501552 : return hlbsa ? g_bsearch_array_lookup (hlbsa, &g_signal_hlbsa_bconfig, &key) : NULL;
414 : : }
415 : :
416 : : static guint
417 : 1618259 : handler_hash (gconstpointer key)
418 : : {
419 : 1618259 : return (guint)((Handler*)key)->sequential_number;
420 : : }
421 : :
422 : : static gboolean
423 : 1078586 : handler_equal (gconstpointer a, gconstpointer b)
424 : : {
425 : 1078586 : Handler *ha = (Handler *)a;
426 : 1078586 : Handler *hb = (Handler *)b;
427 [ + + ]: 2157063 : return (ha->sequential_number == hb->sequential_number) &&
428 [ + + ]: 1078477 : (ha->instance == hb->instance);
429 : : }
430 : :
431 : : static Handler*
432 : 539128 : handler_lookup (gpointer instance,
433 : : gulong handler_id,
434 : : GClosure *closure,
435 : : guint *signal_id_p)
436 : : {
437 : : GBSearchArray *hlbsa;
438 : :
439 [ + + ]: 539128 : if (handler_id)
440 : : {
441 : : Handler key;
442 : 539070 : key.sequential_number = handler_id;
443 : 539070 : key.instance = instance;
444 : 539070 : return g_hash_table_lookup (g_handlers, &key);
445 : :
446 : : }
447 : :
448 : 58 : hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
449 : :
450 [ + + ]: 58 : if (hlbsa)
451 : : {
452 : : guint i;
453 : :
454 [ + - ]: 57 : for (i = 0; i < hlbsa->n_nodes; i++)
455 : : {
456 : 57 : HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, &g_signal_hlbsa_bconfig, i);
457 : : Handler *handler;
458 : :
459 [ + - ]: 58 : for (handler = hlist->handlers; handler; handler = handler->next)
460 [ + - + + ]: 58 : if (closure ? (handler->closure == closure) : (handler->sequential_number == handler_id))
461 : : {
462 [ + - ]: 57 : if (signal_id_p)
463 : 57 : *signal_id_p = hlist->signal_id;
464 : :
465 : 57 : return handler;
466 : : }
467 : : }
468 : : }
469 : :
470 : 1 : return NULL;
471 : : }
472 : :
473 : : static inline HandlerMatch*
474 : 402015 : handler_match_prepend (HandlerMatch *list,
475 : : Handler *handler,
476 : : guint signal_id)
477 : : {
478 : : HandlerMatch *node;
479 : :
480 : 402015 : node = g_slice_new (HandlerMatch);
481 : 402015 : node->handler = handler;
482 : 402015 : node->next = list;
483 : 402015 : node->signal_id = signal_id;
484 : 402015 : handler_ref (handler);
485 : :
486 : 402015 : return node;
487 : : }
488 : : static inline HandlerMatch*
489 : 402015 : handler_match_free1_R (HandlerMatch *node,
490 : : gpointer instance)
491 : : {
492 : 402015 : HandlerMatch *next = node->next;
493 : :
494 : 402015 : handler_unref_R (node->signal_id, instance, node->handler);
495 : 402015 : g_slice_free (HandlerMatch, node);
496 : :
497 : 402015 : return next;
498 : : }
499 : :
500 : : static HandlerMatch*
501 : 402122 : handlers_find (gpointer instance,
502 : : GSignalMatchType mask,
503 : : guint signal_id,
504 : : GQuark detail,
505 : : GClosure *closure,
506 : : gpointer func,
507 : : gpointer data,
508 : : gboolean one_and_only)
509 : : {
510 : 402122 : HandlerMatch *mlist = NULL;
511 : :
512 [ + + ]: 402122 : if (mask & G_SIGNAL_MATCH_ID)
513 : : {
514 : 122 : HandlerList *hlist = handler_list_lookup (signal_id, instance);
515 : : Handler *handler;
516 : 122 : SignalNode *node = NULL;
517 : :
518 [ + + ]: 122 : if (mask & G_SIGNAL_MATCH_FUNC)
519 : : {
520 : 4 : node = LOOKUP_SIGNAL_NODE (signal_id);
521 [ + - - + ]: 4 : if (!node || !node->c_marshaller)
522 : 0 : return NULL;
523 : : }
524 : :
525 : 122 : mask = ~mask;
526 [ + + + + ]: 126 : for (handler = hlist ? hlist->handlers : NULL; handler; handler = handler->next)
527 [ + - ]: 73 : if (handler->sequential_number &&
528 [ + + + - ]: 73 : ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
529 [ - + - - ]: 73 : ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
530 [ + + + - ]: 73 : ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
531 [ + + + - ]: 73 : ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
532 [ + + + - ]: 73 : ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
533 [ + - ]: 2 : G_REAL_CLOSURE (handler->closure)->meta_marshal == NULL &&
534 [ + - ]: 2 : ((GCClosure*) handler->closure)->callback == func)))
535 : : {
536 : 73 : mlist = handler_match_prepend (mlist, handler, signal_id);
537 [ + + ]: 73 : if (one_and_only)
538 : 69 : return mlist;
539 : : }
540 : : }
541 : : else
542 : : {
543 : 402000 : GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
544 : :
545 : 402000 : mask = ~mask;
546 [ + + ]: 402000 : if (hlbsa)
547 : : {
548 : : guint i;
549 : :
550 [ + + ]: 2004514 : for (i = 0; i < hlbsa->n_nodes; i++)
551 : : {
552 : 1602532 : HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, &g_signal_hlbsa_bconfig, i);
553 : 1602532 : SignalNode *node = NULL;
554 : : Handler *handler;
555 : :
556 [ + + ]: 1602532 : if (!(mask & G_SIGNAL_MATCH_FUNC))
557 : : {
558 : 1602524 : node = LOOKUP_SIGNAL_NODE (hlist->signal_id);
559 [ - + ]: 1602524 : if (!node->c_marshaller)
560 : 0 : continue;
561 : : }
562 : :
563 [ + + ]: 3129377 : for (handler = hlist->handlers; handler; handler = handler->next)
564 [ + - ]: 1526845 : if (handler->sequential_number &&
565 [ - + - - ]: 1526845 : ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
566 [ - + - - ]: 1526845 : ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
567 [ + + + + ]: 1526845 : ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
568 [ - + - - ]: 1002182 : ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
569 [ + + + - ]: 1002182 : ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
570 [ + - ]: 1002174 : G_REAL_CLOSURE (handler->closure)->meta_marshal == NULL &&
571 [ + + ]: 1002174 : ((GCClosure*) handler->closure)->callback == func)))
572 : : {
573 : 401942 : mlist = handler_match_prepend (mlist, handler, hlist->signal_id);
574 [ - + ]: 401942 : if (one_and_only)
575 : 0 : return mlist;
576 : : }
577 : : }
578 : : }
579 : : }
580 : :
581 : 402053 : return mlist;
582 : : }
583 : :
584 : : static inline Handler*
585 : 539760 : handler_new (guint signal_id, gpointer instance, gboolean after)
586 : : {
587 : 539760 : Handler *handler = g_slice_new (Handler);
588 : : #ifndef G_DISABLE_CHECKS
589 [ - + ]: 539760 : if (g_handler_sequential_number < 1)
590 : 0 : g_error (G_STRLOC ": handler id overflow, %s", REPORT_BUG);
591 : : #endif
592 : :
593 : 539760 : handler->sequential_number = g_handler_sequential_number++;
594 : 539760 : handler->prev = NULL;
595 : 539760 : handler->next = NULL;
596 : 539760 : handler->detail = 0;
597 : 539760 : handler->signal_id = signal_id;
598 : 539760 : handler->instance = instance;
599 : 539760 : handler->ref_count = 1;
600 : 539760 : handler->block_count = 0;
601 : 539760 : handler->after = after != FALSE;
602 : 539760 : handler->closure = NULL;
603 : 539760 : handler->has_invalid_closure_notify = 0;
604 : :
605 : 539760 : g_hash_table_add (g_handlers, handler);
606 : :
607 : 539760 : return handler;
608 : : }
609 : :
610 : : static inline void
611 : 31721707 : handler_ref (Handler *handler)
612 : : {
613 : 31721707 : g_return_if_fail (handler->ref_count > 0);
614 : :
615 : 31721707 : handler->ref_count++;
616 : : }
617 : :
618 : : static inline void
619 : 32261122 : handler_unref_R (guint signal_id,
620 : : gpointer instance,
621 : : Handler *handler)
622 : : {
623 : 32261122 : g_return_if_fail (handler->ref_count > 0);
624 : :
625 : 32261122 : handler->ref_count--;
626 : :
627 [ + + ]: 32261122 : if (G_UNLIKELY (handler->ref_count == 0))
628 : : {
629 : 539423 : HandlerList *hlist = NULL;
630 : :
631 [ + + ]: 539423 : if (handler->next)
632 : 8272 : handler->next->prev = handler->prev;
633 [ + + ]: 539423 : if (handler->prev) /* watch out for g_signal_handlers_destroy()! */
634 : 11914 : handler->prev->next = handler->next;
635 : : else
636 : : {
637 : 527509 : hlist = handler_list_lookup (signal_id, instance);
638 : 527509 : g_assert (hlist != NULL);
639 : 527509 : hlist->handlers = handler->next;
640 : : }
641 : :
642 [ + + ]: 539423 : if (instance)
643 : : {
644 : : /* check if we are removing the handler pointed to by tail_before */
645 [ + + + + : 538727 : if (!handler->after && (!handler->next || handler->next->after))
+ + ]
646 : : {
647 [ + + ]: 530454 : if (!hlist)
648 : 10300 : hlist = handler_list_lookup (signal_id, instance);
649 [ + - ]: 530454 : if (hlist)
650 : : {
651 : 530454 : g_assert (hlist->tail_before == handler); /* paranoid */
652 : 530454 : hlist->tail_before = handler->prev;
653 : : }
654 : : }
655 : :
656 : : /* check if we are removing the handler pointed to by tail_after */
657 [ + + ]: 538727 : if (!handler->next)
658 : : {
659 [ + + ]: 530455 : if (!hlist)
660 : 2 : hlist = handler_list_lookup (signal_id, instance);
661 [ + - ]: 530455 : if (hlist)
662 : : {
663 : 530455 : g_assert (hlist->tail_after == handler); /* paranoid */
664 : 530455 : hlist->tail_after = handler->prev;
665 : : }
666 : : }
667 : : }
668 : :
669 : 539423 : SIGNAL_UNLOCK ();
670 : 539257 : g_closure_unref (handler->closure);
671 : 539209 : SIGNAL_LOCK ();
672 : 539423 : g_slice_free (Handler, handler);
673 : : }
674 : : }
675 : :
676 : : static void
677 : 539760 : handler_insert (guint signal_id,
678 : : gpointer instance,
679 : : Handler *handler)
680 : : {
681 : : HandlerList *hlist;
682 : :
683 : 539760 : g_assert (handler->prev == NULL && handler->next == NULL); /* paranoid */
684 : :
685 : 539760 : hlist = handler_list_ensure (signal_id, instance);
686 [ + + ]: 539760 : if (!hlist->handlers)
687 : : {
688 : 521129 : hlist->handlers = handler;
689 [ + + ]: 521129 : if (!handler->after)
690 : 521128 : hlist->tail_before = handler;
691 : : }
692 [ + + ]: 18631 : else if (handler->after)
693 : : {
694 : 17 : handler->prev = hlist->tail_after;
695 : 17 : hlist->tail_after->next = handler;
696 : : }
697 : : else
698 : : {
699 [ + + ]: 18614 : if (hlist->tail_before)
700 : : {
701 : 18612 : handler->next = hlist->tail_before->next;
702 [ + + ]: 18612 : if (handler->next)
703 : 28 : handler->next->prev = handler;
704 : 18612 : handler->prev = hlist->tail_before;
705 : 18612 : hlist->tail_before->next = handler;
706 : : }
707 : : else /* insert !after handler into a list of only after handlers */
708 : : {
709 : 2 : handler->next = hlist->handlers;
710 [ + - ]: 2 : if (handler->next)
711 : 2 : handler->next->prev = handler;
712 : 2 : hlist->handlers = handler;
713 : : }
714 : 18614 : hlist->tail_before = handler;
715 : : }
716 : :
717 [ + + ]: 539760 : if (!handler->next)
718 : 539730 : hlist->tail_after = handler;
719 : 539760 : }
720 : :
721 : : static void
722 : 472 : node_update_single_va_closure (SignalNode *node)
723 : : {
724 : 472 : GClosure *closure = NULL;
725 : 472 : gboolean is_after = FALSE;
726 : :
727 : : /* Fast path single-handler without boxing the arguments in GValues */
728 [ + + ]: 472 : if (G_TYPE_IS_OBJECT (node->itype) &&
729 [ + + ]: 398 : (node->flags & (G_SIGNAL_MUST_COLLECT)) == 0 &&
730 [ + + + + ]: 376 : (node->emission_hooks == NULL || node->emission_hooks->hooks == NULL))
731 : : {
732 : : GSignalFlags run_type;
733 : : ClassClosure * cc;
734 : 368 : GBSearchArray *bsa = node->class_closure_bsa;
735 : :
736 [ + + - + ]: 368 : if (bsa == NULL || bsa->n_nodes == 0)
737 : 26 : closure = SINGLE_VA_CLOSURE_EMPTY_MAGIC;
738 [ + + ]: 342 : else if (bsa->n_nodes == 1)
739 : : {
740 : : /* Look for default class closure (can't support non-default as it
741 : : chains up using GValues */
742 : 338 : cc = g_bsearch_array_get_nth (bsa, &g_class_closure_bconfig, 0);
743 [ + - ]: 338 : if (cc->instance_type == 0)
744 : : {
745 : 338 : run_type = node->flags & (G_SIGNAL_RUN_FIRST|G_SIGNAL_RUN_LAST|G_SIGNAL_RUN_CLEANUP);
746 : : /* Only support *one* of run-first or run-last, not multiple or cleanup */
747 [ + + + + ]: 338 : if (run_type == G_SIGNAL_RUN_FIRST ||
748 : : run_type == G_SIGNAL_RUN_LAST)
749 : : {
750 : 333 : closure = cc->closure;
751 : 333 : is_after = (run_type == G_SIGNAL_RUN_LAST);
752 : : }
753 : : }
754 : : }
755 : : }
756 : :
757 : 472 : node->single_va_closure_is_valid = TRUE;
758 : 472 : node->single_va_closure = closure;
759 : 472 : node->single_va_closure_is_after = is_after;
760 : 472 : }
761 : :
762 : : static inline void
763 : 17047792 : emission_push (Emission *emission)
764 : : {
765 : 17047792 : emission->next = g_emissions;
766 : 17047792 : g_emissions = emission;
767 : 17047792 : }
768 : :
769 : : static inline void
770 : 17047784 : emission_pop (Emission *emission)
771 : : {
772 : 17047784 : Emission *node, *last = NULL;
773 : :
774 [ + - ]: 18070174 : for (node = g_emissions; node; last = node, node = last->next)
775 [ + + ]: 18070174 : if (node == emission)
776 : : {
777 [ + + ]: 17047784 : if (last)
778 : 833388 : last->next = node->next;
779 : : else
780 : 16214396 : g_emissions = node->next;
781 : 17047784 : return;
782 : : }
783 : : g_assert_not_reached ();
784 : : }
785 : :
786 : : static inline Emission*
787 : 4616973 : emission_find (guint signal_id,
788 : : GQuark detail,
789 : : gpointer instance)
790 : : {
791 : : Emission *emission;
792 : :
793 [ + + ]: 5803597 : for (emission = g_emissions; emission; emission = emission->next)
794 [ + + ]: 1254487 : if (emission->instance == instance &&
795 [ + + ]: 67930 : emission->ihint.signal_id == signal_id &&
796 [ + + ]: 67869 : emission->ihint.detail == detail)
797 : 67863 : return emission;
798 : 4549110 : return NULL;
799 : : }
800 : :
801 : : static inline Emission*
802 : 24 : emission_find_innermost (gpointer instance)
803 : : {
804 : : Emission *emission;
805 : :
806 [ + - ]: 24 : for (emission = g_emissions; emission; emission = emission->next)
807 [ + - ]: 24 : if (emission->instance == instance)
808 : 24 : return emission;
809 : :
810 : 0 : return NULL;
811 : : }
812 : :
813 : : static gint
814 : 7803629 : signal_key_cmp (gconstpointer node1,
815 : : gconstpointer node2)
816 : : {
817 : 7803629 : const SignalKey *key1 = node1, *key2 = node2;
818 : :
819 [ + + ]: 7803629 : if (key1->itype == key2->itype)
820 [ + + + + ]: 1348120 : return G_BSEARCH_ARRAY_CMP (key1->quark, key2->quark);
821 : : else
822 [ + + - + ]: 6455509 : return G_BSEARCH_ARRAY_CMP (key1->itype, key2->itype);
823 : : }
824 : :
825 : : void
826 : 527 : _g_signal_init (void)
827 : : {
828 : 527 : SIGNAL_LOCK ();
829 [ + - ]: 527 : if (!g_n_signal_nodes)
830 : : {
831 : : /* setup handler list binary searchable array hash table (in german, that'd be one word ;) */
832 : 527 : g_handler_list_bsa_ht = g_hash_table_new (g_direct_hash, NULL);
833 : 527 : g_signal_key_bsa = g_bsearch_array_create (&g_signal_key_bconfig);
834 : :
835 : : /* invalid (0) signal_id */
836 : 527 : g_n_signal_nodes = 1;
837 : 527 : g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
838 : 527 : g_signal_nodes[0] = NULL;
839 : 527 : g_handlers = g_hash_table_new (handler_hash, handler_equal);
840 : : }
841 : 527 : SIGNAL_UNLOCK ();
842 : 527 : }
843 : :
844 : : void
845 : 0 : _g_signals_destroy (GType itype)
846 : : {
847 : : guint i;
848 : :
849 : 0 : SIGNAL_LOCK ();
850 [ # # ]: 0 : for (i = 1; i < g_n_signal_nodes; i++)
851 : : {
852 : 0 : SignalNode *node = g_signal_nodes[i];
853 : :
854 [ # # ]: 0 : if (node->itype == itype)
855 : : {
856 [ # # ]: 0 : if (node->destroyed)
857 : 0 : g_critical (G_STRLOC ": signal \"%s\" of type '%s' already destroyed",
858 : : node->name,
859 : : type_debug_name (node->itype));
860 : : else
861 : 0 : signal_destroy_R (node);
862 : : }
863 : : }
864 : 0 : SIGNAL_UNLOCK ();
865 : 0 : }
866 : :
867 : : /**
868 : : * g_signal_stop_emission:
869 : : * @instance: (type GObject.Object): the object whose signal handlers you wish to stop.
870 : : * @signal_id: the signal identifier, as returned by g_signal_lookup().
871 : : * @detail: the detail which the signal was emitted with.
872 : : *
873 : : * Stops a signal's current emission.
874 : : *
875 : : * This will prevent the default method from running, if the signal was
876 : : * %G_SIGNAL_RUN_LAST and you connected normally (i.e. without the "after"
877 : : * flag).
878 : : *
879 : : * Prints a warning if used on a signal which isn't being emitted.
880 : : */
881 : : void
882 : 1 : g_signal_stop_emission (gpointer instance,
883 : : guint signal_id,
884 : : GQuark detail)
885 : : {
886 : : SignalNode *node;
887 : :
888 : 1 : g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
889 : 1 : g_return_if_fail (signal_id > 0);
890 : :
891 : 1 : SIGNAL_LOCK ();
892 : 1 : node = LOOKUP_SIGNAL_NODE (signal_id);
893 [ + - - + : 1 : if (node && detail && !(node->flags & G_SIGNAL_DETAILED))
- - ]
894 : : {
895 : 0 : g_critical ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
896 : 0 : SIGNAL_UNLOCK ();
897 : 0 : return;
898 : : }
899 [ + - - + : 1 : if (node && g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
- - ]
900 : 1 : {
901 : 1 : Emission *emission = emission_find (signal_id, detail, instance);
902 : :
903 [ + - ]: 1 : if (emission)
904 : : {
905 [ - + ]: 1 : if (emission->state == EMISSION_HOOK)
906 : 0 : g_critical (G_STRLOC ": emission of signal \"%s\" for instance '%p' cannot be stopped from emission hook",
907 : : node->name, instance);
908 [ + - ]: 1 : else if (emission->state == EMISSION_RUN)
909 : 1 : emission->state = EMISSION_STOP;
910 : : }
911 : : else
912 : 0 : g_critical (G_STRLOC ": no emission of signal \"%s\" to stop for instance '%p'",
913 : : node->name, instance);
914 : : }
915 : : else
916 : 0 : g_critical ("%s: signal id '%u' is invalid for instance '%p'", G_STRLOC, signal_id, instance);
917 : 1 : SIGNAL_UNLOCK ();
918 : : }
919 : :
920 : : static void
921 : 26 : signal_finalize_hook (GHookList *hook_list,
922 : : GHook *hook)
923 : : {
924 : 26 : GDestroyNotify destroy = hook->destroy;
925 : :
926 [ - + ]: 26 : if (destroy)
927 : : {
928 : 0 : hook->destroy = NULL;
929 : 0 : SIGNAL_UNLOCK ();
930 : 0 : destroy (hook->data);
931 : 0 : SIGNAL_LOCK ();
932 : : }
933 : 26 : }
934 : :
935 : : /**
936 : : * g_signal_add_emission_hook:
937 : : * @signal_id: the signal identifier, as returned by g_signal_lookup().
938 : : * @detail: the detail on which to call the hook.
939 : : * @hook_func: (not nullable): a #GSignalEmissionHook function.
940 : : * @hook_data: (nullable) (closure hook_func): user data for @hook_func.
941 : : * @data_destroy: (nullable) (destroy hook_data): a #GDestroyNotify for @hook_data.
942 : : *
943 : : * Adds an emission hook for a signal, which will get called for any emission
944 : : * of that signal, independent of the instance. This is possible only
945 : : * for signals which don't have %G_SIGNAL_NO_HOOKS flag set.
946 : : *
947 : : * Returns: the hook id, for later use with g_signal_remove_emission_hook().
948 : : */
949 : : gulong
950 : 26 : g_signal_add_emission_hook (guint signal_id,
951 : : GQuark detail,
952 : : GSignalEmissionHook hook_func,
953 : : gpointer hook_data,
954 : : GDestroyNotify data_destroy)
955 : : {
956 : : static gulong seq_hook_id = 1;
957 : : SignalNode *node;
958 : : GHook *hook;
959 : : SignalHook *signal_hook;
960 : :
961 : 26 : g_return_val_if_fail (signal_id > 0, 0);
962 : 26 : g_return_val_if_fail (hook_func != NULL, 0);
963 : :
964 : 26 : SIGNAL_LOCK ();
965 : 26 : node = LOOKUP_SIGNAL_NODE (signal_id);
966 [ + - - + ]: 26 : if (!node || node->destroyed)
967 : : {
968 : 0 : g_critical ("%s: invalid signal id '%u'", G_STRLOC, signal_id);
969 : 0 : SIGNAL_UNLOCK ();
970 : 0 : return 0;
971 : : }
972 [ - + ]: 26 : if (node->flags & G_SIGNAL_NO_HOOKS)
973 : : {
974 : 0 : g_critical ("%s: signal id '%u' does not support emission hooks (G_SIGNAL_NO_HOOKS flag set)", G_STRLOC, signal_id);
975 : 0 : SIGNAL_UNLOCK ();
976 : 0 : return 0;
977 : : }
978 [ - + - - ]: 26 : if (detail && !(node->flags & G_SIGNAL_DETAILED))
979 : : {
980 : 0 : g_critical ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
981 : 0 : SIGNAL_UNLOCK ();
982 : 0 : return 0;
983 : : }
984 : 26 : node->single_va_closure_is_valid = FALSE;
985 [ + + ]: 26 : if (!node->emission_hooks)
986 : : {
987 : 3 : node->emission_hooks = g_new (GHookList, 1);
988 : 3 : g_hook_list_init (node->emission_hooks, sizeof (SignalHook));
989 : 3 : node->emission_hooks->finalize_hook = signal_finalize_hook;
990 : : }
991 : :
992 : 26 : node_check_deprecated (node);
993 : :
994 : 26 : hook = g_hook_alloc (node->emission_hooks);
995 : 26 : hook->data = hook_data;
996 : 26 : hook->func = (gpointer) hook_func;
997 : 26 : hook->destroy = data_destroy;
998 : 26 : signal_hook = SIGNAL_HOOK (hook);
999 : 26 : signal_hook->detail = detail;
1000 : 26 : node->emission_hooks->seq_id = seq_hook_id;
1001 : 26 : g_hook_append (node->emission_hooks, hook);
1002 : 26 : seq_hook_id = node->emission_hooks->seq_id;
1003 : :
1004 : 26 : SIGNAL_UNLOCK ();
1005 : :
1006 : 26 : return hook->hook_id;
1007 : : }
1008 : :
1009 : : /**
1010 : : * g_signal_remove_emission_hook:
1011 : : * @signal_id: the id of the signal
1012 : : * @hook_id: the id of the emission hook, as returned by
1013 : : * g_signal_add_emission_hook()
1014 : : *
1015 : : * Deletes an emission hook.
1016 : : */
1017 : : void
1018 : 27 : g_signal_remove_emission_hook (guint signal_id,
1019 : : gulong hook_id)
1020 : : {
1021 : : SignalNode *node;
1022 : :
1023 : 27 : g_return_if_fail (signal_id > 0);
1024 : 27 : g_return_if_fail (hook_id > 0);
1025 : :
1026 : 27 : SIGNAL_LOCK ();
1027 : 27 : node = LOOKUP_SIGNAL_NODE (signal_id);
1028 [ + - - + ]: 27 : if (!node || node->destroyed)
1029 : : {
1030 : 0 : g_critical ("%s: invalid signal id '%u'", G_STRLOC, signal_id);
1031 : 0 : goto out;
1032 : : }
1033 [ + - + + ]: 27 : else if (!node->emission_hooks || !g_hook_destroy (node->emission_hooks, hook_id))
1034 : 12 : g_critical ("%s: signal \"%s\" had no hook (%lu) to remove", G_STRLOC, node->name, hook_id);
1035 : :
1036 : 27 : node->single_va_closure_is_valid = FALSE;
1037 : :
1038 : 27 : out:
1039 : 27 : SIGNAL_UNLOCK ();
1040 : : }
1041 : :
1042 : : static inline guint
1043 : 539885 : signal_parse_name (const gchar *name,
1044 : : GType itype,
1045 : : GQuark *detail_p,
1046 : : gboolean force_quark)
1047 : : {
1048 : 539885 : const gchar *colon = strchr (name, ':');
1049 : : guint signal_id;
1050 : :
1051 [ + + ]: 539885 : if (!colon)
1052 : : {
1053 : 539567 : signal_id = signal_id_lookup (name, itype);
1054 [ + + + - ]: 539567 : if (signal_id && detail_p)
1055 : 539564 : *detail_p = 0;
1056 : : }
1057 [ + + ]: 318 : else if (colon[1] == ':')
1058 : : {
1059 : : gchar buffer[32];
1060 : 314 : guint l = colon - name;
1061 : :
1062 [ + + ]: 314 : if (colon[2] == '\0')
1063 : 2 : return 0;
1064 : :
1065 [ + - ]: 312 : if (l < 32)
1066 : : {
1067 : 312 : memcpy (buffer, name, l);
1068 : 312 : buffer[l] = 0;
1069 : 312 : signal_id = signal_id_lookup (buffer, itype);
1070 : : }
1071 : : else
1072 : : {
1073 : 0 : gchar *signal = g_new (gchar, l + 1);
1074 : :
1075 : 0 : memcpy (signal, name, l);
1076 : 0 : signal[l] = 0;
1077 : 0 : signal_id = signal_id_lookup (signal, itype);
1078 : 0 : g_free (signal);
1079 : : }
1080 : :
1081 [ + + + - ]: 312 : if (signal_id && detail_p)
1082 [ + + ]: 311 : *detail_p = (force_quark ? g_quark_from_string : g_quark_try_string) (colon + 2);
1083 : : }
1084 : : else
1085 : 4 : signal_id = 0;
1086 : 539883 : return signal_id;
1087 : : }
1088 : :
1089 : : /**
1090 : : * g_signal_parse_name:
1091 : : * @detailed_signal: a string of the form "signal-name::detail".
1092 : : * @itype: The interface/instance type that introduced "signal-name".
1093 : : * @signal_id_p: (out): Location to store the signal id.
1094 : : * @detail_p: (out): Location to store the detail quark.
1095 : : * @force_detail_quark: %TRUE forces creation of a #GQuark for the detail.
1096 : : *
1097 : : * Internal function to parse a signal name into its @signal_id
1098 : : * and @detail quark.
1099 : : *
1100 : : * Returns: Whether the signal name could successfully be parsed and @signal_id_p and @detail_p contain valid return values.
1101 : : */
1102 : : gboolean
1103 : 49 : g_signal_parse_name (const gchar *detailed_signal,
1104 : : GType itype,
1105 : : guint *signal_id_p,
1106 : : GQuark *detail_p,
1107 : : gboolean force_detail_quark)
1108 : : {
1109 : : SignalNode *node;
1110 : 49 : GQuark detail = 0;
1111 : : guint signal_id;
1112 : :
1113 : 49 : g_return_val_if_fail (detailed_signal != NULL, FALSE);
1114 : 49 : g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), FALSE);
1115 : :
1116 : 49 : SIGNAL_LOCK ();
1117 : 49 : signal_id = signal_parse_name (detailed_signal, itype, &detail, force_detail_quark);
1118 : :
1119 [ + + ]: 49 : node = signal_id ? LOOKUP_SIGNAL_NODE (signal_id) : NULL;
1120 : :
1121 [ + + + - ]: 49 : if (!node || node->destroyed ||
1122 [ + + + + ]: 39 : (detail && !(node->flags & G_SIGNAL_DETAILED)))
1123 : : {
1124 : 11 : SIGNAL_UNLOCK ();
1125 : 11 : return FALSE;
1126 : : }
1127 : :
1128 : 38 : SIGNAL_UNLOCK ();
1129 : :
1130 [ + - ]: 38 : if (signal_id_p)
1131 : 38 : *signal_id_p = signal_id;
1132 [ + - ]: 38 : if (detail_p)
1133 : 38 : *detail_p = detail;
1134 : :
1135 : 38 : return TRUE;
1136 : : }
1137 : :
1138 : : /**
1139 : : * g_signal_stop_emission_by_name:
1140 : : * @instance: (type GObject.Object): the object whose signal handlers you wish to stop.
1141 : : * @detailed_signal: a string of the form "signal-name::detail".
1142 : : *
1143 : : * Stops a signal's current emission.
1144 : : *
1145 : : * This is just like g_signal_stop_emission() except it will look up the
1146 : : * signal id for you.
1147 : : */
1148 : : void
1149 : 1 : g_signal_stop_emission_by_name (gpointer instance,
1150 : : const gchar *detailed_signal)
1151 : : {
1152 : : guint signal_id;
1153 : 1 : GQuark detail = 0;
1154 : : GType itype;
1155 : :
1156 : 1 : g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1157 : 1 : g_return_if_fail (detailed_signal != NULL);
1158 : :
1159 : 1 : SIGNAL_LOCK ();
1160 : 1 : itype = G_TYPE_FROM_INSTANCE (instance);
1161 : 1 : signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
1162 [ + - ]: 1 : if (signal_id)
1163 : : {
1164 : 1 : SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
1165 : :
1166 [ - + - - ]: 1 : if (detail && !(node->flags & G_SIGNAL_DETAILED))
1167 : 0 : g_critical ("%s: signal '%s' does not support details", G_STRLOC, detailed_signal);
1168 [ - + - - ]: 1 : else if (!g_type_is_a (itype, node->itype))
1169 : 0 : g_critical ("%s: signal '%s' is invalid for instance '%p' of type '%s'",
1170 : : G_STRLOC, detailed_signal, instance, g_type_name (itype));
1171 : : else
1172 : : {
1173 : 1 : Emission *emission = emission_find (signal_id, detail, instance);
1174 : :
1175 [ + - ]: 1 : if (emission)
1176 : : {
1177 [ - + ]: 1 : if (emission->state == EMISSION_HOOK)
1178 : 0 : g_critical (G_STRLOC ": emission of signal \"%s\" for instance '%p' cannot be stopped from emission hook",
1179 : : node->name, instance);
1180 [ + - ]: 1 : else if (emission->state == EMISSION_RUN)
1181 : 1 : emission->state = EMISSION_STOP;
1182 : : }
1183 : : else
1184 : 0 : g_critical (G_STRLOC ": no emission of signal \"%s\" to stop for instance '%p'",
1185 : : node->name, instance);
1186 : : }
1187 : : }
1188 : : else
1189 : 0 : g_critical ("%s: signal '%s' is invalid for instance '%p' of type '%s'",
1190 : : G_STRLOC, detailed_signal, instance, g_type_name (itype));
1191 : 1 : SIGNAL_UNLOCK ();
1192 : : }
1193 : :
1194 : : /**
1195 : : * g_signal_lookup:
1196 : : * @name: the signal's name.
1197 : : * @itype: the type that the signal operates on.
1198 : : *
1199 : : * Given the name of the signal and the type of object it connects to, gets
1200 : : * the signal's identifying integer. Emitting the signal by number is
1201 : : * somewhat faster than using the name each time.
1202 : : *
1203 : : * Also tries the ancestors of the given type.
1204 : : *
1205 : : * The type class passed as @itype must already have been instantiated (for
1206 : : * example, using g_type_class_ref()) for this function to work, as signals are
1207 : : * always installed during class initialization.
1208 : : *
1209 : : * See g_signal_new() for details on allowed signal names.
1210 : : *
1211 : : * Returns: the signal's identifying number, or 0 if no signal was found.
1212 : : */
1213 : : guint
1214 : 2364 : g_signal_lookup (const gchar *name,
1215 : : GType itype)
1216 : : {
1217 : : guint signal_id;
1218 : 2364 : g_return_val_if_fail (name != NULL, 0);
1219 : 2364 : g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
1220 : :
1221 : 2364 : SIGNAL_LOCK ();
1222 : 2364 : signal_id = signal_id_lookup (name, itype);
1223 : 2364 : SIGNAL_UNLOCK ();
1224 [ + + ]: 2364 : if (!signal_id)
1225 : : {
1226 : : /* give elaborate warnings */
1227 [ - + ]: 1 : if (!g_type_name (itype))
1228 : 0 : g_critical (G_STRLOC ": unable to look up signal \"%s\" for invalid type id '%"G_GUINTPTR_FORMAT"'",
1229 : : name, (guintptr) itype);
1230 [ - + ]: 1 : else if (!g_signal_is_valid_name (name))
1231 : 0 : g_critical (G_STRLOC ": unable to look up invalid signal name \"%s\" on type '%s'",
1232 : : name, g_type_name (itype));
1233 : : }
1234 : :
1235 : 2364 : return signal_id;
1236 : : }
1237 : :
1238 : : /**
1239 : : * g_signal_list_ids:
1240 : : * @itype: Instance or interface type.
1241 : : * @n_ids: Location to store the number of signal ids for @itype.
1242 : : *
1243 : : * Lists the signals by id that a certain instance or interface type
1244 : : * created. Further information about the signals can be acquired through
1245 : : * g_signal_query().
1246 : : *
1247 : : * Returns: (array length=n_ids) (transfer full): Newly allocated array of signal IDs.
1248 : : */
1249 : : guint*
1250 : 164 : g_signal_list_ids (GType itype,
1251 : : guint *n_ids)
1252 : : {
1253 : : SignalKey *keys;
1254 : : GArray *result;
1255 : : guint n_nodes;
1256 : : guint i;
1257 : :
1258 : 164 : g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), NULL);
1259 : 164 : g_return_val_if_fail (n_ids != NULL, NULL);
1260 : :
1261 : 164 : SIGNAL_LOCK ();
1262 : 164 : keys = g_bsearch_array_get_nth (g_signal_key_bsa, &g_signal_key_bconfig, 0);
1263 : 164 : n_nodes = g_bsearch_array_get_n_nodes (g_signal_key_bsa);
1264 : 164 : result = g_array_new (FALSE, FALSE, sizeof (guint));
1265 : :
1266 [ + + ]: 6949 : for (i = 0; i < n_nodes; i++)
1267 [ + + ]: 6785 : if (keys[i].itype == itype)
1268 : : {
1269 : 113 : g_array_append_val (result, keys[i].signal_id);
1270 : : }
1271 : 164 : *n_ids = result->len;
1272 : 164 : SIGNAL_UNLOCK ();
1273 [ - + ]: 164 : if (!n_nodes)
1274 : : {
1275 : : /* give elaborate warnings */
1276 [ # # ]: 0 : if (!g_type_name (itype))
1277 : 0 : g_critical (G_STRLOC ": unable to list signals for invalid type id '%"G_GUINTPTR_FORMAT"'",
1278 : : (guintptr) itype);
1279 [ # # # # ]: 0 : else if (!G_TYPE_IS_INSTANTIATABLE (itype) && !G_TYPE_IS_INTERFACE (itype))
1280 : 0 : g_critical (G_STRLOC ": unable to list signals of non instantiatable type '%s'",
1281 : : g_type_name (itype));
1282 [ # # # # ]: 0 : else if (!g_type_class_peek (itype) && !G_TYPE_IS_INTERFACE (itype))
1283 : 0 : g_critical (G_STRLOC ": unable to list signals of unloaded type '%s'",
1284 : : g_type_name (itype));
1285 : : }
1286 : :
1287 : 164 : return (guint*) g_array_free (result, FALSE);
1288 : : }
1289 : :
1290 : : /**
1291 : : * g_signal_name:
1292 : : * @signal_id: the signal's identifying number.
1293 : : *
1294 : : * Given the signal's identifier, finds its name.
1295 : : *
1296 : : * Two different signals may have the same name, if they have differing types.
1297 : : *
1298 : : * Returns: (nullable): the signal name, or %NULL if the signal number was invalid.
1299 : : */
1300 : : const gchar *
1301 : 29 : g_signal_name (guint signal_id)
1302 : : {
1303 : : SignalNode *node;
1304 : : const gchar *name;
1305 : :
1306 : 29 : SIGNAL_LOCK ();
1307 : 29 : node = LOOKUP_SIGNAL_NODE (signal_id);
1308 [ + - ]: 29 : name = node ? node->name : NULL;
1309 : 29 : SIGNAL_UNLOCK ();
1310 : :
1311 : 29 : return (char*) name;
1312 : : }
1313 : :
1314 : : /**
1315 : : * g_signal_query:
1316 : : * @signal_id: The signal id of the signal to query information for.
1317 : : * @query: (out caller-allocates) (not optional): A user provided structure that is
1318 : : * filled in with constant values upon success.
1319 : : *
1320 : : * Queries the signal system for in-depth information about a
1321 : : * specific signal. This function will fill in a user-provided
1322 : : * structure to hold signal-specific information. If an invalid
1323 : : * signal id is passed in, the @signal_id member of the #GSignalQuery
1324 : : * is 0. All members filled into the #GSignalQuery structure should
1325 : : * be considered constant and have to be left untouched.
1326 : : */
1327 : : void
1328 : 87 : g_signal_query (guint signal_id,
1329 : : GSignalQuery *query)
1330 : : {
1331 : : SignalNode *node;
1332 : :
1333 : 87 : g_return_if_fail (query != NULL);
1334 : :
1335 : 87 : SIGNAL_LOCK ();
1336 : 87 : node = LOOKUP_SIGNAL_NODE (signal_id);
1337 [ + - - + ]: 87 : if (!node || node->destroyed)
1338 : 0 : query->signal_id = 0;
1339 : : else
1340 : : {
1341 : 87 : query->signal_id = node->signal_id;
1342 : 87 : query->signal_name = node->name;
1343 : 87 : query->itype = node->itype;
1344 : 87 : query->signal_flags = node->flags;
1345 : 87 : query->return_type = node->return_type;
1346 : 87 : query->n_params = node->n_params;
1347 : 87 : query->param_types = node->param_types;
1348 : : }
1349 : 87 : SIGNAL_UNLOCK ();
1350 : : }
1351 : :
1352 : : /**
1353 : : * g_signal_new:
1354 : : * @signal_name: the name for the signal
1355 : : * @itype: the type this signal pertains to. It will also pertain to
1356 : : * types which are derived from this type.
1357 : : * @signal_flags: a combination of #GSignalFlags specifying detail of when
1358 : : * the default handler is to be invoked. You should at least specify
1359 : : * %G_SIGNAL_RUN_FIRST or %G_SIGNAL_RUN_LAST.
1360 : : * @class_offset: The offset of the function pointer in the class structure
1361 : : * for this type. Used to invoke a class method generically. Pass 0 to
1362 : : * not associate a class method slot with this signal.
1363 : : * @accumulator: (nullable) (scope forever): the accumulator for this signal; may be %NULL.
1364 : : * @accu_data: (nullable) (closure accumulator): user data for the @accumulator.
1365 : : * @c_marshaller: (nullable): the function to translate arrays of parameter
1366 : : * values to signal emissions into C language callback invocations or %NULL.
1367 : : * @return_type: the type of return value, or %G_TYPE_NONE for a signal
1368 : : * without a return value.
1369 : : * @n_params: the number of parameter types to follow.
1370 : : * @...: a list of types, one for each parameter.
1371 : : *
1372 : : * Creates a new signal. (This is usually done in the class initializer.)
1373 : : *
1374 : : * A signal name consists of segments consisting of ASCII letters and
1375 : : * digits, separated by either the `-` or `_` character. The first
1376 : : * character of a signal name must be a letter. Names which violate these
1377 : : * rules lead to undefined behaviour. These are the same rules as for property
1378 : : * naming (see g_param_spec_internal()).
1379 : : *
1380 : : * When registering a signal and looking up a signal, either separator can
1381 : : * be used, but they cannot be mixed. Using `-` is considerably more efficient.
1382 : : * Using `_` is discouraged.
1383 : : *
1384 : : * If 0 is used for @class_offset subclasses cannot override the class handler
1385 : : * in their class_init method by doing super_class->signal_handler = my_signal_handler.
1386 : : * Instead they will have to use g_signal_override_class_handler().
1387 : : *
1388 : : * If @c_marshaller is %NULL, g_cclosure_marshal_generic() will be used as
1389 : : * the marshaller for this signal. In some simple cases, g_signal_new()
1390 : : * will use a more optimized c_marshaller and va_marshaller for the signal
1391 : : * instead of g_cclosure_marshal_generic().
1392 : : *
1393 : : * If @c_marshaller is non-%NULL, you need to also specify a va_marshaller
1394 : : * using g_signal_set_va_marshaller() or the generic va_marshaller will
1395 : : * be used.
1396 : : *
1397 : : * Returns: the signal id
1398 : : */
1399 : : guint
1400 : 1784 : g_signal_new (const gchar *signal_name,
1401 : : GType itype,
1402 : : GSignalFlags signal_flags,
1403 : : guint class_offset,
1404 : : GSignalAccumulator accumulator,
1405 : : gpointer accu_data,
1406 : : GSignalCMarshaller c_marshaller,
1407 : : GType return_type,
1408 : : guint n_params,
1409 : : ...)
1410 : : {
1411 : : va_list args;
1412 : : guint signal_id;
1413 : :
1414 : 1784 : g_return_val_if_fail (signal_name != NULL, 0);
1415 : :
1416 : 1784 : va_start (args, n_params);
1417 : :
1418 [ + + ]: 3507 : signal_id = g_signal_new_valist (signal_name, itype, signal_flags,
1419 : 1723 : class_offset ? g_signal_type_cclosure_new (itype, class_offset) : NULL,
1420 : : accumulator, accu_data, c_marshaller,
1421 : : return_type, n_params, args);
1422 : :
1423 : 1784 : va_end (args);
1424 : :
1425 : 1784 : return signal_id;
1426 : : }
1427 : :
1428 : : /**
1429 : : * g_signal_new_class_handler:
1430 : : * @signal_name: the name for the signal
1431 : : * @itype: the type this signal pertains to. It will also pertain to
1432 : : * types which are derived from this type.
1433 : : * @signal_flags: a combination of #GSignalFlags specifying detail of when
1434 : : * the default handler is to be invoked. You should at least specify
1435 : : * %G_SIGNAL_RUN_FIRST or %G_SIGNAL_RUN_LAST.
1436 : : * @class_handler: (nullable) (scope forever): a #GCallback which acts as class implementation of
1437 : : * this signal. Used to invoke a class method generically. Pass %NULL to
1438 : : * not associate a class method with this signal.
1439 : : * @accumulator: (nullable) (scope forever): the accumulator for this signal; may be %NULL.
1440 : : * @accu_data: (nullable) (closure accumulator): user data for the @accumulator.
1441 : : * @c_marshaller: (nullable): the function to translate arrays of parameter
1442 : : * values to signal emissions into C language callback invocations or %NULL.
1443 : : * @return_type: the type of return value, or %G_TYPE_NONE for a signal
1444 : : * without a return value.
1445 : : * @n_params: the number of parameter types to follow.
1446 : : * @...: a list of types, one for each parameter.
1447 : : *
1448 : : * Creates a new signal. (This is usually done in the class initializer.)
1449 : : *
1450 : : * This is a variant of g_signal_new() that takes a C callback instead
1451 : : * of a class offset for the signal's class handler. This function
1452 : : * doesn't need a function pointer exposed in the class structure of
1453 : : * an object definition, instead the function pointer is passed
1454 : : * directly and can be overridden by derived classes with
1455 : : * g_signal_override_class_closure() or
1456 : : * g_signal_override_class_handler() and chained to with
1457 : : * g_signal_chain_from_overridden() or
1458 : : * g_signal_chain_from_overridden_handler().
1459 : : *
1460 : : * See g_signal_new() for information about signal names.
1461 : : *
1462 : : * If c_marshaller is %NULL, g_cclosure_marshal_generic() will be used as
1463 : : * the marshaller for this signal.
1464 : : *
1465 : : * Returns: the signal id
1466 : : *
1467 : : * Since: 2.18
1468 : : */
1469 : : guint
1470 : 1 : g_signal_new_class_handler (const gchar *signal_name,
1471 : : GType itype,
1472 : : GSignalFlags signal_flags,
1473 : : GCallback class_handler,
1474 : : GSignalAccumulator accumulator,
1475 : : gpointer accu_data,
1476 : : GSignalCMarshaller c_marshaller,
1477 : : GType return_type,
1478 : : guint n_params,
1479 : : ...)
1480 : : {
1481 : : va_list args;
1482 : : guint signal_id;
1483 : :
1484 : 1 : g_return_val_if_fail (signal_name != NULL, 0);
1485 : :
1486 : 1 : va_start (args, n_params);
1487 : :
1488 [ + - ]: 2 : signal_id = g_signal_new_valist (signal_name, itype, signal_flags,
1489 : 1 : class_handler ? g_cclosure_new (class_handler, NULL, NULL) : NULL,
1490 : : accumulator, accu_data, c_marshaller,
1491 : : return_type, n_params, args);
1492 : :
1493 : 1 : va_end (args);
1494 : :
1495 : 1 : return signal_id;
1496 : : }
1497 : :
1498 : : static inline ClassClosure*
1499 : 16806730 : signal_find_class_closure (SignalNode *node,
1500 : : GType itype)
1501 : : {
1502 : 16806730 : GBSearchArray *bsa = node->class_closure_bsa;
1503 : : ClassClosure *cc;
1504 : :
1505 [ + + ]: 16806730 : if (bsa)
1506 : : {
1507 : : ClassClosure key;
1508 : :
1509 : : /* cc->instance_type is 0 for default closure */
1510 : :
1511 [ + + ]: 16787546 : if (g_bsearch_array_get_n_nodes (bsa) == 1)
1512 : : {
1513 : 16787511 : cc = g_bsearch_array_get_nth (bsa, &g_class_closure_bconfig, 0);
1514 [ + - + - ]: 16787511 : if (cc && cc->instance_type == 0) /* check for default closure */
1515 : 16787511 : return cc;
1516 : : }
1517 : :
1518 : 35 : key.instance_type = itype;
1519 : 35 : cc = g_bsearch_array_lookup (bsa, &g_class_closure_bconfig, &key);
1520 [ + + + - ]: 50 : while (!cc && key.instance_type)
1521 : : {
1522 : 15 : key.instance_type = g_type_parent (key.instance_type);
1523 : 15 : cc = g_bsearch_array_lookup (bsa, &g_class_closure_bconfig, &key);
1524 : : }
1525 : : }
1526 : : else
1527 : 19184 : cc = NULL;
1528 : 19219 : return cc;
1529 : : }
1530 : :
1531 : : static inline GClosure*
1532 : 16806655 : signal_lookup_closure (SignalNode *node,
1533 : : GTypeInstance *instance)
1534 : : {
1535 : : ClassClosure *cc;
1536 : :
1537 : 16806655 : cc = signal_find_class_closure (node, G_TYPE_FROM_INSTANCE (instance));
1538 [ + + ]: 16806655 : return cc ? cc->closure : NULL;
1539 : : }
1540 : :
1541 : : static void
1542 : 1732 : signal_add_class_closure (SignalNode *node,
1543 : : GType itype,
1544 : : GClosure *closure)
1545 : : {
1546 : : ClassClosure key;
1547 : :
1548 : 1732 : node->single_va_closure_is_valid = FALSE;
1549 : :
1550 [ + + ]: 1732 : if (!node->class_closure_bsa)
1551 : 1725 : node->class_closure_bsa = g_bsearch_array_create (&g_class_closure_bconfig);
1552 : 1732 : key.instance_type = itype;
1553 : 1732 : key.closure = g_closure_ref (closure);
1554 : 1732 : node->class_closure_bsa = g_bsearch_array_insert (node->class_closure_bsa,
1555 : : &g_class_closure_bconfig,
1556 : : &key);
1557 : 1732 : g_closure_sink (closure);
1558 [ + - + - : 1732 : if (node->c_marshaller && closure && G_CLOSURE_NEEDS_MARSHAL (closure))
+ - ]
1559 : : {
1560 : 1732 : g_closure_set_marshal (closure, node->c_marshaller);
1561 [ + + ]: 1732 : if (node->va_marshaller)
1562 : 635 : _g_closure_set_va_marshal (closure, node->va_marshaller);
1563 : : }
1564 : 1732 : }
1565 : :
1566 : : /**
1567 : : * g_signal_newv:
1568 : : * @signal_name: the name for the signal
1569 : : * @itype: the type this signal pertains to. It will also pertain to
1570 : : * types which are derived from this type
1571 : : * @signal_flags: a combination of #GSignalFlags specifying detail of when
1572 : : * the default handler is to be invoked. You should at least specify
1573 : : * %G_SIGNAL_RUN_FIRST or %G_SIGNAL_RUN_LAST
1574 : : * @class_closure: (nullable): The closure to invoke on signal emission;
1575 : : * may be %NULL
1576 : : * @accumulator: (nullable) (scope forever): the accumulator for this signal; may be %NULL
1577 : : * @accu_data: (nullable) (closure accumulator): user data for the @accumulator
1578 : : * @c_marshaller: (nullable): the function to translate arrays of
1579 : : * parameter values to signal emissions into C language callback
1580 : : * invocations or %NULL
1581 : : * @return_type: the type of return value, or %G_TYPE_NONE for a signal
1582 : : * without a return value
1583 : : * @n_params: the length of @param_types
1584 : : * @param_types: (array length=n_params) (nullable): an array of types, one for
1585 : : * each parameter (may be %NULL if @n_params is zero)
1586 : : *
1587 : : * Creates a new signal. (This is usually done in the class initializer.)
1588 : : *
1589 : : * See g_signal_new() for details on allowed signal names.
1590 : : *
1591 : : * If c_marshaller is %NULL, g_cclosure_marshal_generic() will be used as
1592 : : * the marshaller for this signal.
1593 : : *
1594 : : * Returns: the signal id
1595 : : */
1596 : : guint
1597 : 1786 : g_signal_newv (const gchar *signal_name,
1598 : : GType itype,
1599 : : GSignalFlags signal_flags,
1600 : : GClosure *class_closure,
1601 : : GSignalAccumulator accumulator,
1602 : : gpointer accu_data,
1603 : : GSignalCMarshaller c_marshaller,
1604 : : GType return_type,
1605 : : guint n_params,
1606 : : GType *param_types)
1607 : : {
1608 : : const gchar *name;
1609 : 1786 : gchar *signal_name_copy = NULL;
1610 : : guint signal_id, i;
1611 : : SignalNode *node;
1612 : : GSignalCMarshaller builtin_c_marshaller;
1613 : : GSignalCVaMarshaller builtin_va_marshaller;
1614 : : GSignalCVaMarshaller va_marshaller;
1615 : :
1616 : 1786 : g_return_val_if_fail (signal_name != NULL, 0);
1617 : 1786 : g_return_val_if_fail (g_signal_is_valid_name (signal_name), 0);
1618 : 1786 : g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
1619 [ + + ]: 1786 : if (n_params)
1620 : 1554 : g_return_val_if_fail (param_types != NULL, 0);
1621 : 1786 : g_return_val_if_fail ((return_type & G_SIGNAL_TYPE_STATIC_SCOPE) == 0, 0);
1622 [ + + ]: 1786 : if (return_type == (G_TYPE_NONE & ~G_SIGNAL_TYPE_STATIC_SCOPE))
1623 : 1354 : g_return_val_if_fail (accumulator == NULL, 0);
1624 [ + + ]: 1786 : if (!accumulator)
1625 : 1366 : g_return_val_if_fail (accu_data == NULL, 0);
1626 : 1786 : g_return_val_if_fail ((signal_flags & G_SIGNAL_ACCUMULATOR_FIRST_RUN) == 0, 0);
1627 : :
1628 [ + + ]: 1786 : if (!is_canonical (signal_name))
1629 : : {
1630 : 1 : signal_name_copy = g_strdup (signal_name);
1631 : 1 : canonicalize_key (signal_name_copy);
1632 : 1 : name = signal_name_copy;
1633 : : }
1634 : : else
1635 : : {
1636 : 1785 : name = signal_name;
1637 : : }
1638 : :
1639 : 1786 : SIGNAL_LOCK ();
1640 : :
1641 : 1786 : signal_id = signal_id_lookup (name, itype);
1642 : 1786 : node = LOOKUP_SIGNAL_NODE (signal_id);
1643 [ - + - - ]: 1786 : if (node && !node->destroyed)
1644 : : {
1645 [ # # ]: 0 : g_critical (G_STRLOC ": signal \"%s\" already exists in the '%s' %s",
1646 : : name,
1647 : : type_debug_name (node->itype),
1648 : : G_TYPE_IS_INTERFACE (node->itype) ? "interface" : "class ancestry");
1649 : 0 : g_free (signal_name_copy);
1650 : 0 : SIGNAL_UNLOCK ();
1651 : 0 : return 0;
1652 : : }
1653 [ - + - - ]: 1786 : if (node && node->itype != itype)
1654 : : {
1655 : 0 : g_critical (G_STRLOC ": signal \"%s\" for type '%s' was previously created for type '%s'",
1656 : : name,
1657 : : type_debug_name (itype),
1658 : : type_debug_name (node->itype));
1659 : 0 : g_free (signal_name_copy);
1660 : 0 : SIGNAL_UNLOCK ();
1661 : 0 : return 0;
1662 : : }
1663 [ + + ]: 4758 : for (i = 0; i < n_params; i++)
1664 [ - + ]: 2972 : if (!G_TYPE_IS_VALUE (param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE))
1665 : : {
1666 : 0 : g_critical (G_STRLOC ": parameter %d of type '%s' for signal \"%s::%s\" is not a value type",
1667 : : i + 1, type_debug_name (param_types[i]), type_debug_name (itype), name);
1668 : 0 : g_free (signal_name_copy);
1669 : 0 : SIGNAL_UNLOCK ();
1670 : 0 : return 0;
1671 : : }
1672 [ + + - + ]: 1786 : if (return_type != G_TYPE_NONE && !G_TYPE_IS_VALUE (return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE))
1673 : : {
1674 : 0 : g_critical (G_STRLOC ": return value of type '%s' for signal \"%s::%s\" is not a value type",
1675 : : type_debug_name (return_type), type_debug_name (itype), name);
1676 : 0 : g_free (signal_name_copy);
1677 : 0 : SIGNAL_UNLOCK ();
1678 : 0 : return 0;
1679 : : }
1680 : :
1681 : : /* setup permanent portion of signal node */
1682 [ + - ]: 1786 : if (!node)
1683 : : {
1684 : : SignalKey key;
1685 : :
1686 : 1786 : signal_id = g_n_signal_nodes++;
1687 : 1786 : node = g_new (SignalNode, 1);
1688 : 1786 : node->signal_id = signal_id;
1689 : 1786 : g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
1690 : 1786 : g_signal_nodes[signal_id] = node;
1691 : 1786 : node->itype = itype;
1692 : 1786 : key.itype = itype;
1693 : 1786 : key.signal_id = signal_id;
1694 : 1786 : node->name = g_intern_string (name);
1695 : 1786 : key.quark = g_quark_from_string (name);
1696 : 1786 : g_signal_key_bsa = g_bsearch_array_insert (g_signal_key_bsa, &g_signal_key_bconfig, &key);
1697 : :
1698 : 1786 : TRACE(GOBJECT_SIGNAL_NEW(signal_id, name, itype));
1699 : : }
1700 : 1786 : node->destroyed = FALSE;
1701 : :
1702 : : /* setup reinitializable portion */
1703 : 1786 : node->single_va_closure_is_valid = FALSE;
1704 : 1786 : node->flags = signal_flags & G_SIGNAL_FLAGS_MASK;
1705 : 1786 : node->n_params = n_params;
1706 : 1786 : node->param_types = g_memdup2 (param_types, sizeof (GType) * n_params);
1707 : 1786 : node->return_type = return_type;
1708 : 1786 : node->class_closure_bsa = NULL;
1709 [ + + ]: 1786 : if (accumulator)
1710 : : {
1711 : 420 : node->accumulator = g_new (SignalAccumulator, 1);
1712 : 420 : node->accumulator->func = accumulator;
1713 : 420 : node->accumulator->data = accu_data;
1714 : : }
1715 : : else
1716 : 1366 : node->accumulator = NULL;
1717 : :
1718 : 1786 : builtin_c_marshaller = NULL;
1719 : 1786 : builtin_va_marshaller = NULL;
1720 : :
1721 : : /* Pick up built-in va marshallers for standard types, and
1722 : : instead of generic marshaller if no marshaller specified */
1723 [ + + + + ]: 1786 : if (n_params == 0 && return_type == G_TYPE_NONE)
1724 : : {
1725 : 205 : builtin_c_marshaller = g_cclosure_marshal_VOID__VOID;
1726 : 205 : builtin_va_marshaller = g_cclosure_marshal_VOID__VOIDv;
1727 : : }
1728 [ + + + + ]: 1581 : else if (n_params == 1 && return_type == G_TYPE_NONE)
1729 : : {
1730 : : #define ADD_CHECK(__type__) \
1731 : : else if (g_type_is_a (param_types[0] & ~G_SIGNAL_TYPE_STATIC_SCOPE, G_TYPE_ ##__type__)) \
1732 : : { \
1733 : : builtin_c_marshaller = g_cclosure_marshal_VOID__ ## __type__; \
1734 : : builtin_va_marshaller = g_cclosure_marshal_VOID__ ## __type__ ##v; \
1735 : : }
1736 : :
1737 : : if (0) {}
1738 [ + + - + ]: 484 : ADD_CHECK (BOOLEAN)
1739 [ + - - + ]: 462 : ADD_CHECK (CHAR)
1740 [ + - - + ]: 462 : ADD_CHECK (UCHAR)
1741 [ + + - + ]: 462 : ADD_CHECK (INT)
1742 [ + - - + ]: 452 : ADD_CHECK (UINT)
1743 [ + - - + ]: 452 : ADD_CHECK (LONG)
1744 [ + - - + ]: 452 : ADD_CHECK (ULONG)
1745 [ + - + + ]: 452 : ADD_CHECK (ENUM)
1746 [ + - - + ]: 447 : ADD_CHECK (FLAGS)
1747 [ + - - + ]: 447 : ADD_CHECK (FLOAT)
1748 [ + + - + ]: 447 : ADD_CHECK (DOUBLE)
1749 [ + + - + ]: 446 : ADD_CHECK (STRING)
1750 [ + + - + ]: 402 : ADD_CHECK (PARAM)
1751 [ + - - + ]: 83 : ADD_CHECK (BOXED)
1752 [ + + - + ]: 83 : ADD_CHECK (POINTER)
1753 [ + + + + ]: 82 : ADD_CHECK (OBJECT)
1754 [ - + - - ]: 16 : ADD_CHECK (VARIANT)
1755 : : }
1756 : :
1757 [ + + ]: 1786 : if (c_marshaller == NULL)
1758 : : {
1759 [ + + ]: 680 : if (builtin_c_marshaller)
1760 : : {
1761 : 659 : c_marshaller = builtin_c_marshaller;
1762 : 659 : va_marshaller = builtin_va_marshaller;
1763 : : }
1764 : : else
1765 : : {
1766 : 21 : c_marshaller = g_cclosure_marshal_generic;
1767 : 21 : va_marshaller = g_cclosure_marshal_generic_va;
1768 : : }
1769 : : }
1770 : : else
1771 : 1106 : va_marshaller = NULL;
1772 : :
1773 : 1786 : node->c_marshaller = c_marshaller;
1774 : 1786 : node->va_marshaller = va_marshaller;
1775 : 1786 : node->emission_hooks = NULL;
1776 [ + + ]: 1786 : if (class_closure)
1777 : 1725 : signal_add_class_closure (node, 0, class_closure);
1778 : :
1779 : 1786 : SIGNAL_UNLOCK ();
1780 : :
1781 : 1786 : g_free (signal_name_copy);
1782 : :
1783 : 1786 : return signal_id;
1784 : : }
1785 : :
1786 : : /**
1787 : : * g_signal_set_va_marshaller:
1788 : : * @signal_id: the signal id
1789 : : * @instance_type: the instance type on which to set the marshaller.
1790 : : * @va_marshaller: the marshaller to set.
1791 : : *
1792 : : * Change the #GSignalCVaMarshaller used for a given signal. This is a
1793 : : * specialised form of the marshaller that can often be used for the
1794 : : * common case of a single connected signal handler and avoids the
1795 : : * overhead of #GValue. Its use is optional.
1796 : : *
1797 : : * Since: 2.32
1798 : : */
1799 : : void
1800 : 986 : g_signal_set_va_marshaller (guint signal_id,
1801 : : GType instance_type,
1802 : : GSignalCVaMarshaller va_marshaller)
1803 : : {
1804 : : SignalNode *node;
1805 : :
1806 : 986 : g_return_if_fail (signal_id > 0);
1807 : 986 : g_return_if_fail (va_marshaller != NULL);
1808 : :
1809 : 986 : SIGNAL_LOCK ();
1810 : 986 : node = LOOKUP_SIGNAL_NODE (signal_id);
1811 [ + - ]: 986 : if (node)
1812 : : {
1813 : 986 : node->va_marshaller = va_marshaller;
1814 [ + + ]: 986 : if (node->class_closure_bsa)
1815 : : {
1816 : 978 : ClassClosure *cc = g_bsearch_array_get_nth (node->class_closure_bsa, &g_class_closure_bconfig, 0);
1817 [ + - ]: 978 : if (cc->closure->marshal == node->c_marshaller)
1818 : 978 : _g_closure_set_va_marshal (cc->closure, va_marshaller);
1819 : : }
1820 : :
1821 : 986 : node->single_va_closure_is_valid = FALSE;
1822 : : }
1823 : :
1824 : 986 : SIGNAL_UNLOCK ();
1825 : : }
1826 : :
1827 : :
1828 : : /**
1829 : : * g_signal_new_valist:
1830 : : * @signal_name: the name for the signal
1831 : : * @itype: the type this signal pertains to. It will also pertain to
1832 : : * types which are derived from this type.
1833 : : * @signal_flags: a combination of #GSignalFlags specifying detail of when
1834 : : * the default handler is to be invoked. You should at least specify
1835 : : * %G_SIGNAL_RUN_FIRST or %G_SIGNAL_RUN_LAST.
1836 : : * @class_closure: (nullable): The closure to invoke on signal emission; may be %NULL.
1837 : : * @accumulator: (nullable) (scope forever): the accumulator for this signal; may be %NULL.
1838 : : * @accu_data: (nullable) (closure accumulator): user data for the @accumulator.
1839 : : * @c_marshaller: (nullable): the function to translate arrays of parameter
1840 : : * values to signal emissions into C language callback invocations or %NULL.
1841 : : * @return_type: the type of return value, or %G_TYPE_NONE for a signal
1842 : : * without a return value.
1843 : : * @n_params: the number of parameter types in @args.
1844 : : * @args: va_list of #GType, one for each parameter.
1845 : : *
1846 : : * Creates a new signal. (This is usually done in the class initializer.)
1847 : : *
1848 : : * See g_signal_new() for details on allowed signal names.
1849 : : *
1850 : : * If c_marshaller is %NULL, g_cclosure_marshal_generic() will be used as
1851 : : * the marshaller for this signal.
1852 : : *
1853 : : * Returns: the signal id
1854 : : */
1855 : : guint
1856 : 1785 : g_signal_new_valist (const gchar *signal_name,
1857 : : GType itype,
1858 : : GSignalFlags signal_flags,
1859 : : GClosure *class_closure,
1860 : : GSignalAccumulator accumulator,
1861 : : gpointer accu_data,
1862 : : GSignalCMarshaller c_marshaller,
1863 : : GType return_type,
1864 : : guint n_params,
1865 : : va_list args)
1866 : : {
1867 : : /* Somewhat arbitrarily reserve 200 bytes. That should cover the majority
1868 : : * of cases where n_params is small and still be small enough for what we
1869 : : * want to put on the stack. */
1870 : : GType param_types_stack[200 / sizeof (GType)];
1871 : 1785 : GType *param_types_heap = NULL;
1872 : : GType *param_types;
1873 : : guint i;
1874 : : guint signal_id;
1875 : :
1876 : 1785 : param_types = param_types_stack;
1877 [ + + ]: 1785 : if (n_params > 0)
1878 : : {
1879 [ - + ]: 1554 : if (G_UNLIKELY (n_params > G_N_ELEMENTS (param_types_stack)))
1880 : : {
1881 : 0 : param_types_heap = g_new (GType, n_params);
1882 : 0 : param_types = param_types_heap;
1883 : : }
1884 : :
1885 [ + + ]: 4526 : for (i = 0; i < n_params; i++)
1886 : 2972 : param_types[i] = va_arg (args, GType);
1887 : : }
1888 : :
1889 : 1785 : signal_id = g_signal_newv (signal_name, itype, signal_flags,
1890 : : class_closure, accumulator, accu_data, c_marshaller,
1891 : : return_type, n_params, param_types);
1892 : 1785 : g_free (param_types_heap);
1893 : :
1894 : 1785 : return signal_id;
1895 : : }
1896 : :
1897 : : static void
1898 : 0 : signal_destroy_R (SignalNode *signal_node)
1899 : : {
1900 : 0 : SignalNode node = *signal_node;
1901 : :
1902 : 0 : signal_node->destroyed = TRUE;
1903 : :
1904 : : /* reentrancy caution, zero out real contents first */
1905 : 0 : signal_node->single_va_closure_is_valid = FALSE;
1906 : 0 : signal_node->n_params = 0;
1907 : 0 : signal_node->param_types = NULL;
1908 : 0 : signal_node->return_type = 0;
1909 : 0 : signal_node->class_closure_bsa = NULL;
1910 : 0 : signal_node->accumulator = NULL;
1911 : 0 : signal_node->c_marshaller = NULL;
1912 : 0 : signal_node->va_marshaller = NULL;
1913 : 0 : signal_node->emission_hooks = NULL;
1914 : :
1915 : : #ifdef G_ENABLE_DEBUG
1916 : : /* check current emissions */
1917 : : {
1918 : : Emission *emission;
1919 : :
1920 [ # # ]: 0 : for (emission = g_emissions; emission; emission = emission->next)
1921 [ # # ]: 0 : if (emission->ihint.signal_id == node.signal_id)
1922 : 0 : g_critical (G_STRLOC ": signal \"%s\" being destroyed is currently in emission (instance '%p')",
1923 : : node.name, emission->instance);
1924 : : }
1925 : : #endif
1926 : :
1927 : : /* free contents that need to
1928 : : */
1929 : 0 : SIGNAL_UNLOCK ();
1930 : 0 : g_free (node.param_types);
1931 [ # # ]: 0 : if (node.class_closure_bsa)
1932 : : {
1933 : : guint i;
1934 : :
1935 [ # # ]: 0 : for (i = 0; i < node.class_closure_bsa->n_nodes; i++)
1936 : : {
1937 : 0 : ClassClosure *cc = g_bsearch_array_get_nth (node.class_closure_bsa, &g_class_closure_bconfig, i);
1938 : :
1939 : 0 : g_closure_unref (cc->closure);
1940 : : }
1941 : 0 : g_bsearch_array_free (node.class_closure_bsa, &g_class_closure_bconfig);
1942 : : }
1943 : 0 : g_free (node.accumulator);
1944 [ # # ]: 0 : if (node.emission_hooks)
1945 : : {
1946 : 0 : g_hook_list_clear (node.emission_hooks);
1947 : 0 : g_free (node.emission_hooks);
1948 : : }
1949 : 0 : SIGNAL_LOCK ();
1950 : 0 : }
1951 : :
1952 : : /**
1953 : : * g_signal_override_class_closure:
1954 : : * @signal_id: the signal id
1955 : : * @instance_type: the instance type on which to override the class closure
1956 : : * for the signal.
1957 : : * @class_closure: the closure.
1958 : : *
1959 : : * Overrides the class closure (i.e. the default handler) for the given signal
1960 : : * for emissions on instances of @instance_type. @instance_type must be derived
1961 : : * from the type to which the signal belongs.
1962 : : *
1963 : : * See g_signal_chain_from_overridden() and
1964 : : * g_signal_chain_from_overridden_handler() for how to chain up to the
1965 : : * parent class closure from inside the overridden one.
1966 : : */
1967 : : void
1968 : 7 : g_signal_override_class_closure (guint signal_id,
1969 : : GType instance_type,
1970 : : GClosure *class_closure)
1971 : : {
1972 : : SignalNode *node;
1973 : :
1974 : 7 : g_return_if_fail (signal_id > 0);
1975 : 7 : g_return_if_fail (class_closure != NULL);
1976 : :
1977 : 7 : SIGNAL_LOCK ();
1978 : 7 : node = LOOKUP_SIGNAL_NODE (signal_id);
1979 : 7 : node_check_deprecated (node);
1980 [ + - - + ]: 7 : if (!g_type_is_a (instance_type, node->itype))
1981 : 0 : g_critical ("%s: type '%s' cannot be overridden for signal id '%u'", G_STRLOC, type_debug_name (instance_type), signal_id);
1982 : : else
1983 : : {
1984 : 7 : ClassClosure *cc = signal_find_class_closure (node, instance_type);
1985 : :
1986 [ + - - + ]: 7 : if (cc && cc->instance_type == instance_type)
1987 : 0 : g_critical ("%s: type '%s' is already overridden for signal id '%u'", G_STRLOC, type_debug_name (instance_type), signal_id);
1988 : : else
1989 : 7 : signal_add_class_closure (node, instance_type, class_closure);
1990 : : }
1991 : 7 : SIGNAL_UNLOCK ();
1992 : : }
1993 : :
1994 : : /**
1995 : : * g_signal_override_class_handler:
1996 : : * @signal_name: the name for the signal
1997 : : * @instance_type: the instance type on which to override the class handler
1998 : : * for the signal.
1999 : : * @class_handler: (scope forever): the handler.
2000 : : *
2001 : : * Overrides the class closure (i.e. the default handler) for the
2002 : : * given signal for emissions on instances of @instance_type with
2003 : : * callback @class_handler. @instance_type must be derived from the
2004 : : * type to which the signal belongs.
2005 : : *
2006 : : * See g_signal_chain_from_overridden() and
2007 : : * g_signal_chain_from_overridden_handler() for how to chain up to the
2008 : : * parent class closure from inside the overridden one.
2009 : : *
2010 : : * Since: 2.18
2011 : : */
2012 : : void
2013 : 2 : g_signal_override_class_handler (const gchar *signal_name,
2014 : : GType instance_type,
2015 : : GCallback class_handler)
2016 : : {
2017 : : guint signal_id;
2018 : :
2019 : 2 : g_return_if_fail (signal_name != NULL);
2020 : 2 : g_return_if_fail (instance_type != G_TYPE_NONE);
2021 : 2 : g_return_if_fail (class_handler != NULL);
2022 : :
2023 : 2 : signal_id = g_signal_lookup (signal_name, instance_type);
2024 : :
2025 [ + - ]: 2 : if (signal_id)
2026 : 2 : g_signal_override_class_closure (signal_id, instance_type,
2027 : : g_cclosure_new (class_handler, NULL, NULL));
2028 : : else
2029 : 0 : g_critical ("%s: signal name '%s' is invalid for type id '%"G_GUINTPTR_FORMAT"'",
2030 : : G_STRLOC, signal_name, (guintptr) instance_type);
2031 : :
2032 : : }
2033 : :
2034 : : /**
2035 : : * g_signal_chain_from_overridden:
2036 : : * @instance_and_params: (array): the argument list of the signal emission.
2037 : : * The first element in the array is a #GValue for the instance the signal
2038 : : * is being emitted on. The rest are any arguments to be passed to the signal.
2039 : : * @return_value: Location for the return value.
2040 : : *
2041 : : * Calls the original class closure of a signal. This function should only
2042 : : * be called from an overridden class closure; see
2043 : : * g_signal_override_class_closure() and
2044 : : * g_signal_override_class_handler().
2045 : : */
2046 : : void
2047 : 9 : g_signal_chain_from_overridden (const GValue *instance_and_params,
2048 : : GValue *return_value)
2049 : : {
2050 : 9 : GType chain_type = 0, restore_type = 0;
2051 : 9 : Emission *emission = NULL;
2052 : 9 : GClosure *closure = NULL;
2053 : 9 : guint n_params = 0;
2054 : : gpointer instance;
2055 : :
2056 : 9 : g_return_if_fail (instance_and_params != NULL);
2057 : 9 : instance = g_value_peek_pointer (instance_and_params);
2058 : 9 : g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
2059 : :
2060 : 9 : SIGNAL_LOCK ();
2061 : 9 : emission = emission_find_innermost (instance);
2062 [ + - ]: 9 : if (emission)
2063 : : {
2064 : 9 : SignalNode *node = LOOKUP_SIGNAL_NODE (emission->ihint.signal_id);
2065 : :
2066 : 9 : g_assert (node != NULL); /* paranoid */
2067 : :
2068 : : /* we should probably do the same parameter checks as g_signal_emit() here.
2069 : : */
2070 [ + - ]: 9 : if (emission->chain_type != G_TYPE_NONE)
2071 : : {
2072 : 9 : ClassClosure *cc = signal_find_class_closure (node, emission->chain_type);
2073 : :
2074 : 9 : g_assert (cc != NULL); /* closure currently in call stack */
2075 : :
2076 : 9 : n_params = node->n_params;
2077 : 9 : restore_type = cc->instance_type;
2078 : 9 : cc = signal_find_class_closure (node, g_type_parent (cc->instance_type));
2079 [ + - + - ]: 9 : if (cc && cc->instance_type != restore_type)
2080 : : {
2081 : 9 : closure = cc->closure;
2082 : 9 : chain_type = cc->instance_type;
2083 : : }
2084 : : }
2085 : : else
2086 : 0 : g_critical ("%s: signal id '%u' cannot be chained from current emission stage for instance '%p'", G_STRLOC, node->signal_id, instance);
2087 : : }
2088 : : else
2089 : 0 : g_critical ("%s: no signal is currently being emitted for instance '%p'", G_STRLOC, instance);
2090 : :
2091 [ + - ]: 9 : if (closure)
2092 : : {
2093 : 9 : emission->chain_type = chain_type;
2094 : 9 : SIGNAL_UNLOCK ();
2095 : 9 : g_closure_invoke (closure,
2096 : : return_value,
2097 : : n_params + 1,
2098 : : instance_and_params,
2099 : 9 : &emission->ihint);
2100 : 9 : SIGNAL_LOCK ();
2101 : 9 : emission->chain_type = restore_type;
2102 : : }
2103 : 9 : SIGNAL_UNLOCK ();
2104 : : }
2105 : :
2106 : : /**
2107 : : * g_signal_chain_from_overridden_handler: (skip)
2108 : : * @instance: (type GObject.TypeInstance): the instance the signal is being
2109 : : * emitted on.
2110 : : * @...: parameters to be passed to the parent class closure, followed by a
2111 : : * location for the return value. If the return type of the signal
2112 : : * is %G_TYPE_NONE, the return value location can be omitted.
2113 : : *
2114 : : * Calls the original class closure of a signal. This function should
2115 : : * only be called from an overridden class closure; see
2116 : : * g_signal_override_class_closure() and
2117 : : * g_signal_override_class_handler().
2118 : : *
2119 : : * Since: 2.18
2120 : : */
2121 : : void
2122 : 3 : g_signal_chain_from_overridden_handler (gpointer instance,
2123 : : ...)
2124 : : {
2125 : 3 : GType chain_type = 0, restore_type = 0;
2126 : 3 : Emission *emission = NULL;
2127 : 3 : GClosure *closure = NULL;
2128 : 3 : SignalNode *node = NULL;
2129 : 3 : guint n_params = 0;
2130 : :
2131 : 3 : g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
2132 : :
2133 : 3 : SIGNAL_LOCK ();
2134 : 3 : emission = emission_find_innermost (instance);
2135 [ + - ]: 3 : if (emission)
2136 : : {
2137 : 3 : node = LOOKUP_SIGNAL_NODE (emission->ihint.signal_id);
2138 : :
2139 : 3 : g_assert (node != NULL); /* paranoid */
2140 : :
2141 : : /* we should probably do the same parameter checks as g_signal_emit() here.
2142 : : */
2143 [ + - ]: 3 : if (emission->chain_type != G_TYPE_NONE)
2144 : : {
2145 : 3 : ClassClosure *cc = signal_find_class_closure (node, emission->chain_type);
2146 : :
2147 : 3 : g_assert (cc != NULL); /* closure currently in call stack */
2148 : :
2149 : 3 : n_params = node->n_params;
2150 : 3 : restore_type = cc->instance_type;
2151 : 3 : cc = signal_find_class_closure (node, g_type_parent (cc->instance_type));
2152 [ + - + - ]: 3 : if (cc && cc->instance_type != restore_type)
2153 : : {
2154 : 3 : closure = cc->closure;
2155 : 3 : chain_type = cc->instance_type;
2156 : : }
2157 : : }
2158 : : else
2159 : 0 : g_critical ("%s: signal id '%u' cannot be chained from current emission stage for instance '%p'", G_STRLOC, node->signal_id, instance);
2160 : : }
2161 : : else
2162 : 0 : g_critical ("%s: no signal is currently being emitted for instance '%p'", G_STRLOC, instance);
2163 : :
2164 [ + - ]: 3 : if (closure)
2165 : : {
2166 : : GValue *instance_and_params;
2167 : : GType signal_return_type;
2168 : : GValue *param_values;
2169 : : va_list var_args;
2170 : : guint i;
2171 : :
2172 : 3 : va_start (var_args, instance);
2173 : :
2174 : 3 : signal_return_type = node->return_type;
2175 [ + - ]: 3 : instance_and_params = g_newa0 (GValue, n_params + 1);
2176 : 3 : param_values = instance_and_params + 1;
2177 : :
2178 [ + + ]: 9 : for (i = 0; i < node->n_params; i++)
2179 : : {
2180 : : gchar *error;
2181 : 6 : GType ptype = node->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE;
2182 : 6 : gboolean static_scope = node->param_types[i] & G_SIGNAL_TYPE_STATIC_SCOPE;
2183 : :
2184 : 6 : SIGNAL_UNLOCK ();
2185 [ - + - - : 12 : G_VALUE_COLLECT_INIT (param_values + i, ptype,
- - + - +
+ ]
2186 : : var_args,
2187 : : static_scope ? G_VALUE_NOCOPY_CONTENTS : 0,
2188 : : &error);
2189 [ - + ]: 6 : if (error)
2190 : : {
2191 : 0 : g_critical ("%s: %s", G_STRLOC, error);
2192 : 0 : g_free (error);
2193 : :
2194 : : /* we purposely leak the value here, it might not be
2195 : : * in a correct state if an error condition occurred
2196 : : */
2197 [ # # ]: 0 : while (i--)
2198 : 0 : g_value_unset (param_values + i);
2199 : :
2200 : 0 : va_end (var_args);
2201 : 0 : return;
2202 : : }
2203 : 6 : SIGNAL_LOCK ();
2204 : : }
2205 : :
2206 : 3 : SIGNAL_UNLOCK ();
2207 : 3 : g_value_init_from_instance (instance_and_params, instance);
2208 : 3 : SIGNAL_LOCK ();
2209 : :
2210 : 3 : emission->chain_type = chain_type;
2211 : 3 : SIGNAL_UNLOCK ();
2212 : :
2213 [ - + ]: 3 : if (signal_return_type == G_TYPE_NONE)
2214 : : {
2215 : 0 : g_closure_invoke (closure,
2216 : : NULL,
2217 : : n_params + 1,
2218 : : instance_and_params,
2219 : 0 : &emission->ihint);
2220 : : }
2221 : : else
2222 : : {
2223 : 3 : GValue return_value = G_VALUE_INIT;
2224 : 3 : gchar *error = NULL;
2225 : 3 : GType rtype = signal_return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE;
2226 : 3 : gboolean static_scope = signal_return_type & G_SIGNAL_TYPE_STATIC_SCOPE;
2227 : :
2228 : 3 : g_value_init (&return_value, rtype);
2229 : :
2230 : 3 : g_closure_invoke (closure,
2231 : : &return_value,
2232 : : n_params + 1,
2233 : : instance_and_params,
2234 : 3 : &emission->ihint);
2235 : :
2236 [ - + - - : 6 : G_VALUE_LCOPY (&return_value,
- - + - +
+ ]
2237 : : var_args,
2238 : : static_scope ? G_VALUE_NOCOPY_CONTENTS : 0,
2239 : : &error);
2240 [ + - ]: 3 : if (!error)
2241 : : {
2242 : 3 : g_value_unset (&return_value);
2243 : : }
2244 : : else
2245 : : {
2246 : 0 : g_critical ("%s: %s", G_STRLOC, error);
2247 : 0 : g_free (error);
2248 : :
2249 : : /* we purposely leak the value here, it might not be
2250 : : * in a correct state if an error condition occurred
2251 : : */
2252 : : }
2253 : : }
2254 : :
2255 [ + + ]: 9 : for (i = 0; i < n_params; i++)
2256 : 6 : g_value_unset (param_values + i);
2257 : 3 : g_value_unset (instance_and_params);
2258 : :
2259 : 3 : va_end (var_args);
2260 : :
2261 : 3 : SIGNAL_LOCK ();
2262 : 3 : emission->chain_type = restore_type;
2263 : : }
2264 : 3 : SIGNAL_UNLOCK ();
2265 : : }
2266 : :
2267 : : /**
2268 : : * g_signal_get_invocation_hint:
2269 : : * @instance: (type GObject.Object): the instance to query
2270 : : *
2271 : : * Returns the invocation hint of the innermost signal emission of instance.
2272 : : *
2273 : : * Returns: (transfer none) (nullable): the invocation hint of the innermost
2274 : : * signal emission, or %NULL if not found.
2275 : : */
2276 : : GSignalInvocationHint*
2277 : 12 : g_signal_get_invocation_hint (gpointer instance)
2278 : : {
2279 : 12 : Emission *emission = NULL;
2280 : :
2281 : 12 : g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), NULL);
2282 : :
2283 : 12 : SIGNAL_LOCK ();
2284 : 12 : emission = emission_find_innermost (instance);
2285 : 12 : SIGNAL_UNLOCK ();
2286 : :
2287 [ + - ]: 12 : return emission ? &emission->ihint : NULL;
2288 : : }
2289 : :
2290 : : /**
2291 : : * g_signal_connect_closure_by_id:
2292 : : * @instance: (type GObject.Object): the instance to connect to.
2293 : : * @signal_id: the id of the signal.
2294 : : * @detail: the detail.
2295 : : * @closure: (not nullable): the closure to connect.
2296 : : * @after: whether the handler should be called before or after the
2297 : : * default handler of the signal.
2298 : : *
2299 : : * Connects a closure to a signal for a particular object.
2300 : : *
2301 : : * If @closure is a floating reference (see g_closure_sink()), this function
2302 : : * takes ownership of @closure.
2303 : : *
2304 : : * This function cannot fail. If the given signal doesn’t exist, a critical
2305 : : * warning is emitted.
2306 : : *
2307 : : * Returns: the handler ID (always greater than 0)
2308 : : */
2309 : : gulong
2310 : 338 : g_signal_connect_closure_by_id (gpointer instance,
2311 : : guint signal_id,
2312 : : GQuark detail,
2313 : : GClosure *closure,
2314 : : gboolean after)
2315 : : {
2316 : : SignalNode *node;
2317 : 338 : gulong handler_seq_no = 0;
2318 : :
2319 : 338 : g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
2320 : 338 : g_return_val_if_fail (signal_id > 0, 0);
2321 : 338 : g_return_val_if_fail (closure != NULL, 0);
2322 : :
2323 : 338 : SIGNAL_LOCK ();
2324 : 338 : node = LOOKUP_SIGNAL_NODE (signal_id);
2325 [ + - ]: 338 : if (node)
2326 : : {
2327 [ + + - + ]: 338 : if (detail && !(node->flags & G_SIGNAL_DETAILED))
2328 : 0 : g_critical ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
2329 [ + + - + ]: 338 : else if (!g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
2330 : 0 : g_critical ("%s: signal id '%u' is invalid for instance '%p'", G_STRLOC, signal_id, instance);
2331 : : else
2332 : : {
2333 : 338 : Handler *handler = handler_new (signal_id, instance, after);
2334 : :
2335 [ + - ]: 338 : if (G_TYPE_IS_OBJECT (node->itype))
2336 : 338 : _g_object_set_has_signal_handler ((GObject *) instance, signal_id);
2337 : :
2338 : 338 : handler_seq_no = handler->sequential_number;
2339 : 338 : handler->detail = detail;
2340 : 338 : handler->closure = g_closure_ref (closure);
2341 : 338 : g_closure_sink (closure);
2342 : 338 : add_invalid_closure_notify (handler, instance);
2343 : 338 : handler_insert (signal_id, instance, handler);
2344 [ + - + + ]: 338 : if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (closure))
2345 : : {
2346 : 322 : g_closure_set_marshal (closure, node->c_marshaller);
2347 [ + - ]: 322 : if (node->va_marshaller)
2348 : 322 : _g_closure_set_va_marshal (closure, node->va_marshaller);
2349 : : }
2350 : : }
2351 : : }
2352 : : else
2353 : 0 : g_critical ("%s: signal id '%u' is invalid for instance '%p'", G_STRLOC, signal_id, instance);
2354 : 338 : SIGNAL_UNLOCK ();
2355 : :
2356 : 338 : return handler_seq_no;
2357 : : }
2358 : :
2359 : : /**
2360 : : * g_signal_connect_closure:
2361 : : * @instance: (type GObject.Object): the instance to connect to.
2362 : : * @detailed_signal: a string of the form "signal-name::detail".
2363 : : * @closure: (not nullable): the closure to connect.
2364 : : * @after: whether the handler should be called before or after the
2365 : : * default handler of the signal.
2366 : : *
2367 : : * Connects a closure to a signal for a particular object.
2368 : : *
2369 : : * If @closure is a floating reference (see g_closure_sink()), this function
2370 : : * takes ownership of @closure.
2371 : : *
2372 : : * This function cannot fail. If the given signal doesn’t exist, a critical
2373 : : * warning is emitted.
2374 : : *
2375 : : * Returns: the handler ID (always greater than 0)
2376 : : */
2377 : : gulong
2378 : 58 : g_signal_connect_closure (gpointer instance,
2379 : : const gchar *detailed_signal,
2380 : : GClosure *closure,
2381 : : gboolean after)
2382 : : {
2383 : : guint signal_id;
2384 : 58 : gulong handler_seq_no = 0;
2385 : 58 : GQuark detail = 0;
2386 : : GType itype;
2387 : :
2388 : 58 : g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
2389 : 58 : g_return_val_if_fail (detailed_signal != NULL, 0);
2390 : 58 : g_return_val_if_fail (closure != NULL, 0);
2391 : :
2392 : 58 : SIGNAL_LOCK ();
2393 : 58 : itype = G_TYPE_FROM_INSTANCE (instance);
2394 : 58 : signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
2395 [ + - ]: 58 : if (signal_id)
2396 : : {
2397 : 58 : SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
2398 : :
2399 [ - + - - ]: 58 : if (detail && !(node->flags & G_SIGNAL_DETAILED))
2400 : 0 : g_critical ("%s: signal '%s' does not support details", G_STRLOC, detailed_signal);
2401 [ - + - - ]: 58 : else if (!g_type_is_a (itype, node->itype))
2402 : 0 : g_critical ("%s: signal '%s' is invalid for instance '%p' of type '%s'",
2403 : : G_STRLOC, detailed_signal, instance, g_type_name (itype));
2404 : : else
2405 : : {
2406 : 58 : Handler *handler = handler_new (signal_id, instance, after);
2407 : :
2408 [ + - ]: 58 : if (G_TYPE_IS_OBJECT (node->itype))
2409 : 58 : _g_object_set_has_signal_handler ((GObject *) instance, signal_id);
2410 : :
2411 : 58 : handler_seq_no = handler->sequential_number;
2412 : 58 : handler->detail = detail;
2413 : 58 : handler->closure = g_closure_ref (closure);
2414 : 58 : g_closure_sink (closure);
2415 : 58 : add_invalid_closure_notify (handler, instance);
2416 : 58 : handler_insert (signal_id, instance, handler);
2417 [ + - + + ]: 58 : if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure))
2418 : : {
2419 : 57 : g_closure_set_marshal (handler->closure, node->c_marshaller);
2420 [ + + ]: 57 : if (node->va_marshaller)
2421 : 56 : _g_closure_set_va_marshal (handler->closure, node->va_marshaller);
2422 : : }
2423 : : }
2424 : : }
2425 : : else
2426 : 0 : g_critical ("%s: signal '%s' is invalid for instance '%p' of type '%s'",
2427 : : G_STRLOC, detailed_signal, instance, g_type_name (itype));
2428 : 58 : SIGNAL_UNLOCK ();
2429 : :
2430 : 58 : return handler_seq_no;
2431 : : }
2432 : :
2433 : : static void
2434 : 539397 : node_check_deprecated (const SignalNode *node)
2435 : : {
2436 : : static const gchar * g_enable_diagnostic = NULL;
2437 : :
2438 [ + + ]: 539397 : if (G_UNLIKELY (!g_enable_diagnostic))
2439 : : {
2440 : 190 : g_enable_diagnostic = g_getenv ("G_ENABLE_DIAGNOSTIC");
2441 [ - + ]: 190 : if (!g_enable_diagnostic)
2442 : 0 : g_enable_diagnostic = "0";
2443 : : }
2444 : :
2445 [ + + ]: 539397 : if (g_enable_diagnostic[0] == '1')
2446 : : {
2447 [ - + ]: 539393 : if (node->flags & G_SIGNAL_DEPRECATED)
2448 : : {
2449 : 0 : g_warning ("The signal %s::%s is deprecated and shouldn't be used "
2450 : : "anymore. It will be removed in a future version.",
2451 : : type_debug_name (node->itype), node->name);
2452 : : }
2453 : : }
2454 : 539397 : }
2455 : :
2456 : : /**
2457 : : * g_signal_connect_data:
2458 : : * @instance: (type GObject.Object): the instance to connect to.
2459 : : * @detailed_signal: a string of the form "signal-name::detail".
2460 : : * @c_handler: (not nullable): the #GCallback to connect.
2461 : : * @data: (nullable) (closure c_handler): data to pass to @c_handler calls.
2462 : : * @destroy_data: (nullable) (destroy data): a #GClosureNotify for @data.
2463 : : * @connect_flags: a combination of #GConnectFlags.
2464 : : *
2465 : : * Connects a #GCallback function to a signal for a particular object. Similar
2466 : : * to g_signal_connect(), but allows to provide a #GClosureNotify for the data
2467 : : * which will be called when the signal handler is disconnected and no longer
2468 : : * used. Specify @connect_flags if you need `..._after()` or
2469 : : * `..._swapped()` variants of this function.
2470 : : *
2471 : : * This function cannot fail. If the given signal doesn’t exist, a critical
2472 : : * warning is emitted.
2473 : : *
2474 : : * Returns: the handler ID (always greater than 0)
2475 : : */
2476 : : gulong
2477 : 539109 : g_signal_connect_data (gpointer instance,
2478 : : const gchar *detailed_signal,
2479 : : GCallback c_handler,
2480 : : gpointer data,
2481 : : GClosureNotify destroy_data,
2482 : : GConnectFlags connect_flags)
2483 : : {
2484 : : guint signal_id;
2485 : 539109 : gulong handler_seq_no = 0;
2486 : 539109 : GQuark detail = 0;
2487 : : GType itype;
2488 : : gboolean swapped, after;
2489 : :
2490 : 539109 : g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
2491 : 539109 : g_return_val_if_fail (detailed_signal != NULL, 0);
2492 : 539109 : g_return_val_if_fail (c_handler != NULL, 0);
2493 : :
2494 : 539109 : swapped = (connect_flags & G_CONNECT_SWAPPED) != FALSE;
2495 : 539109 : after = (connect_flags & G_CONNECT_AFTER) != FALSE;
2496 : :
2497 : 539109 : SIGNAL_LOCK ();
2498 : 539364 : itype = G_TYPE_FROM_INSTANCE (instance);
2499 : 539364 : signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
2500 [ + - ]: 539364 : if (signal_id)
2501 : : {
2502 : 539364 : SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
2503 : :
2504 : 539364 : node_check_deprecated (node);
2505 : :
2506 [ + + - + ]: 539364 : if (detail && !(node->flags & G_SIGNAL_DETAILED))
2507 : 0 : g_critical ("%s: signal '%s' does not support details", G_STRLOC, detailed_signal);
2508 [ + + - + ]: 539364 : else if (!g_type_is_a (itype, node->itype))
2509 : 0 : g_critical ("%s: signal '%s' is invalid for instance '%p' of type '%s'",
2510 : : G_STRLOC, detailed_signal, instance, g_type_name (itype));
2511 : : else
2512 : : {
2513 : 539364 : Handler *handler = handler_new (signal_id, instance, after);
2514 : :
2515 [ + + ]: 539364 : if (G_TYPE_IS_OBJECT (node->itype))
2516 : 138901 : _g_object_set_has_signal_handler ((GObject *) instance, signal_id);
2517 : :
2518 : 539364 : handler_seq_no = handler->sequential_number;
2519 : 539364 : handler->detail = detail;
2520 [ + + ]: 539364 : handler->closure = g_closure_ref ((swapped ? g_cclosure_new_swap : g_cclosure_new) (c_handler, data, destroy_data));
2521 : 539364 : g_closure_sink (handler->closure);
2522 : 539364 : handler_insert (signal_id, instance, handler);
2523 [ + - + - ]: 539364 : if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure))
2524 : : {
2525 : 539364 : g_closure_set_marshal (handler->closure, node->c_marshaller);
2526 [ + + ]: 539364 : if (node->va_marshaller)
2527 : 539264 : _g_closure_set_va_marshal (handler->closure, node->va_marshaller);
2528 : : }
2529 : : }
2530 : : }
2531 : : else
2532 : 0 : g_critical ("%s: signal '%s' is invalid for instance '%p' of type '%s'",
2533 : : G_STRLOC, detailed_signal, instance, g_type_name (itype));
2534 : 539364 : SIGNAL_UNLOCK ();
2535 : :
2536 : 539345 : return handler_seq_no;
2537 : : }
2538 : :
2539 : : static void
2540 : : signal_handler_block_unlocked (gpointer instance,
2541 : : gulong handler_id);
2542 : :
2543 : : /**
2544 : : * g_signal_handler_block:
2545 : : * @instance: (type GObject.Object): The instance to block the signal handler of.
2546 : : * @handler_id: Handler id of the handler to be blocked.
2547 : : *
2548 : : * Blocks a handler of an instance so it will not be called during any
2549 : : * signal emissions unless it is unblocked again. Thus "blocking" a
2550 : : * signal handler means to temporarily deactivate it, a signal handler
2551 : : * has to be unblocked exactly the same amount of times it has been
2552 : : * blocked before to become active again.
2553 : : *
2554 : : * The @handler_id has to be a valid signal handler id, connected to a
2555 : : * signal of @instance.
2556 : : */
2557 : : void
2558 : 186 : g_signal_handler_block (gpointer instance,
2559 : : gulong handler_id)
2560 : : {
2561 : 186 : g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
2562 : 186 : g_return_if_fail (handler_id > 0);
2563 : :
2564 : 186 : SIGNAL_LOCK ();
2565 : 186 : signal_handler_block_unlocked (instance, handler_id);
2566 : 186 : SIGNAL_UNLOCK ();
2567 : : }
2568 : :
2569 : : static void
2570 : 189 : signal_handler_block_unlocked (gpointer instance,
2571 : : gulong handler_id)
2572 : : {
2573 : : Handler *handler;
2574 : :
2575 : 189 : handler = handler_lookup (instance, handler_id, NULL, NULL);
2576 [ + - ]: 189 : if (handler)
2577 : : {
2578 : : #ifndef G_DISABLE_CHECKS
2579 [ - + ]: 189 : if (handler->block_count >= HANDLER_MAX_BLOCK_COUNT - 1)
2580 : 0 : g_error (G_STRLOC ": handler block_count overflow, %s", REPORT_BUG);
2581 : : #endif
2582 : 189 : handler->block_count += 1;
2583 : : }
2584 : : else
2585 : 0 : g_critical ("%s: instance '%p' has no handler with id '%lu'", G_STRLOC, instance, handler_id);
2586 : 189 : }
2587 : :
2588 : : static void
2589 : : signal_handler_unblock_unlocked (gpointer instance,
2590 : : gulong handler_id);
2591 : :
2592 : : /**
2593 : : * g_signal_handler_unblock:
2594 : : * @instance: (type GObject.Object): The instance to unblock the signal handler of.
2595 : : * @handler_id: Handler id of the handler to be unblocked.
2596 : : *
2597 : : * Undoes the effect of a previous g_signal_handler_block() call. A
2598 : : * blocked handler is skipped during signal emissions and will not be
2599 : : * invoked, unblocking it (for exactly the amount of times it has been
2600 : : * blocked before) reverts its "blocked" state, so the handler will be
2601 : : * recognized by the signal system and is called upon future or
2602 : : * currently ongoing signal emissions (since the order in which
2603 : : * handlers are called during signal emissions is deterministic,
2604 : : * whether the unblocked handler in question is called as part of a
2605 : : * currently ongoing emission depends on how far that emission has
2606 : : * proceeded yet).
2607 : : *
2608 : : * The @handler_id has to be a valid id of a signal handler that is
2609 : : * connected to a signal of @instance and is currently blocked.
2610 : : */
2611 : : void
2612 : 170 : g_signal_handler_unblock (gpointer instance,
2613 : : gulong handler_id)
2614 : : {
2615 : 170 : g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
2616 : 170 : g_return_if_fail (handler_id > 0);
2617 : :
2618 : 170 : SIGNAL_LOCK ();
2619 : 170 : signal_handler_unblock_unlocked (instance, handler_id);
2620 : 170 : SIGNAL_UNLOCK ();
2621 : : }
2622 : :
2623 : : static void
2624 : 173 : signal_handler_unblock_unlocked (gpointer instance,
2625 : : gulong handler_id)
2626 : : {
2627 : : Handler *handler;
2628 : :
2629 : 173 : handler = handler_lookup (instance, handler_id, NULL, NULL);
2630 [ + - ]: 173 : if (handler)
2631 : : {
2632 [ + - ]: 173 : if (handler->block_count)
2633 : 173 : handler->block_count -= 1;
2634 : : else
2635 : 0 : g_critical (G_STRLOC ": handler '%lu' of instance '%p' is not blocked", handler_id, instance);
2636 : : }
2637 : : else
2638 : 0 : g_critical ("%s: instance '%p' has no handler with id '%lu'", G_STRLOC, instance, handler_id);
2639 : 173 : }
2640 : :
2641 : : static void
2642 : : signal_handler_disconnect_unlocked (gpointer instance,
2643 : : gulong handler_id);
2644 : :
2645 : : /**
2646 : : * g_signal_handler_disconnect:
2647 : : * @instance: (type GObject.Object): The instance to remove the signal handler from.
2648 : : * @handler_id: Handler id of the handler to be disconnected.
2649 : : *
2650 : : * Disconnects a handler from an instance so it will not be called during
2651 : : * any future or currently ongoing emissions of the signal it has been
2652 : : * connected to. The @handler_id becomes invalid and may be reused.
2653 : : *
2654 : : * The @handler_id has to be a valid signal handler id, connected to a
2655 : : * signal of @instance.
2656 : : */
2657 : : void
2658 : 136739 : g_signal_handler_disconnect (gpointer instance,
2659 : : gulong handler_id)
2660 : : {
2661 : 136739 : g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
2662 : 136739 : g_return_if_fail (handler_id > 0);
2663 : :
2664 : 136739 : SIGNAL_LOCK ();
2665 : 136739 : signal_handler_disconnect_unlocked (instance, handler_id);
2666 : 136739 : SIGNAL_UNLOCK ();
2667 : : }
2668 : :
2669 : : static void
2670 : 538679 : signal_handler_disconnect_unlocked (gpointer instance,
2671 : : gulong handler_id)
2672 : : {
2673 : : Handler *handler;
2674 : :
2675 : 538679 : handler = handler_lookup (instance, handler_id, 0, 0);
2676 [ + + ]: 538679 : if (handler)
2677 : : {
2678 : 538676 : g_hash_table_remove (g_handlers, handler);
2679 : 538676 : handler->sequential_number = 0;
2680 : 538676 : handler->block_count = 1;
2681 : 538676 : remove_invalid_closure_notify (handler, instance);
2682 : 538676 : handler_unref_R (handler->signal_id, instance, handler);
2683 : : }
2684 : : else
2685 : 3 : g_critical ("%s: instance '%p' has no handler with id '%lu'", G_STRLOC, instance, handler_id);
2686 : 538679 : }
2687 : :
2688 : : /**
2689 : : * g_signal_handler_is_connected:
2690 : : * @instance: (type GObject.Object): The instance where a signal handler is sought.
2691 : : * @handler_id: the handler ID.
2692 : : *
2693 : : * Returns whether @handler_id is the ID of a handler connected to @instance.
2694 : : *
2695 : : * Returns: whether @handler_id identifies a handler connected to @instance.
2696 : : */
2697 : : gboolean
2698 : 30 : g_signal_handler_is_connected (gpointer instance,
2699 : : gulong handler_id)
2700 : : {
2701 : : Handler *handler;
2702 : : gboolean connected;
2703 : :
2704 : 30 : g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
2705 : :
2706 : 30 : SIGNAL_LOCK ();
2707 : 30 : handler = handler_lookup (instance, handler_id, NULL, NULL);
2708 : 30 : connected = handler != NULL;
2709 : 30 : SIGNAL_UNLOCK ();
2710 : :
2711 : 30 : return connected;
2712 : : }
2713 : :
2714 : : /**
2715 : : * g_signal_handlers_destroy:
2716 : : * @instance: (type GObject.Object): The instance whose signal handlers are destroyed
2717 : : *
2718 : : * Destroy all signal handlers of a type instance. This function is
2719 : : * an implementation detail of the #GObject dispose implementation,
2720 : : * and should not be used outside of the type system.
2721 : : */
2722 : : void
2723 : 7401603 : g_signal_handlers_destroy (gpointer instance)
2724 : : {
2725 : : GBSearchArray *hlbsa;
2726 : :
2727 : 7401603 : g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
2728 : :
2729 : 7401603 : SIGNAL_LOCK ();
2730 : 7403016 : hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
2731 [ + + ]: 7403016 : if (hlbsa)
2732 : : {
2733 : : guint i;
2734 : :
2735 : : /* reentrancy caution, delete instance trace first */
2736 : 106491 : g_hash_table_remove (g_handler_list_bsa_ht, instance);
2737 : :
2738 [ + + ]: 213381 : for (i = 0; i < hlbsa->n_nodes; i++)
2739 : : {
2740 : 106890 : HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, &g_signal_hlbsa_bconfig, i);
2741 : 106890 : Handler *handler = hlist->handlers;
2742 : :
2743 [ + + ]: 107586 : while (handler)
2744 : : {
2745 : 696 : Handler *tmp = handler;
2746 : :
2747 : 696 : handler = tmp->next;
2748 : 696 : tmp->block_count = 1;
2749 : : /* cruel unlink, this works because _all_ handlers vanish */
2750 : 696 : tmp->next = NULL;
2751 : 696 : tmp->prev = tmp;
2752 [ + - ]: 696 : if (tmp->sequential_number)
2753 : : {
2754 : 696 : g_hash_table_remove (g_handlers, tmp);
2755 : 696 : remove_invalid_closure_notify (tmp, instance);
2756 : 696 : tmp->sequential_number = 0;
2757 : 696 : handler_unref_R (0, NULL, tmp);
2758 : : }
2759 : : }
2760 : : }
2761 : 106491 : g_bsearch_array_free (hlbsa, &g_signal_hlbsa_bconfig);
2762 : : }
2763 : 7403016 : SIGNAL_UNLOCK ();
2764 : : }
2765 : :
2766 : : /**
2767 : : * g_signal_handler_find:
2768 : : * @instance: (type GObject.Object): The instance owning the signal handler to be found.
2769 : : * @mask: Mask indicating which of @signal_id, @detail, @closure, @func
2770 : : * and/or @data the handler has to match.
2771 : : * @signal_id: Signal the handler has to be connected to.
2772 : : * @detail: Signal detail the handler has to be connected to.
2773 : : * @closure: (nullable): The closure the handler will invoke.
2774 : : * @func: The C closure callback of the handler (useless for non-C closures).
2775 : : * @data: (nullable) (closure closure): The closure data of the handler's closure.
2776 : : *
2777 : : * Finds the first signal handler that matches certain selection criteria.
2778 : : * The criteria mask is passed as an OR-ed combination of #GSignalMatchType
2779 : : * flags, and the criteria values are passed as arguments.
2780 : : * The match @mask has to be non-0 for successful matches.
2781 : : * If no handler was found, 0 is returned.
2782 : : *
2783 : : * Returns: A valid non-0 signal handler id for a successful match.
2784 : : */
2785 : : gulong
2786 : 13 : g_signal_handler_find (gpointer instance,
2787 : : GSignalMatchType mask,
2788 : : guint signal_id,
2789 : : GQuark detail,
2790 : : GClosure *closure,
2791 : : gpointer func,
2792 : : gpointer data)
2793 : : {
2794 : 13 : gulong handler_seq_no = 0;
2795 : :
2796 : 13 : g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
2797 : 13 : g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
2798 : :
2799 [ + - ]: 13 : if (mask & G_SIGNAL_MATCH_MASK)
2800 : : {
2801 : : HandlerMatch *mlist;
2802 : :
2803 : 13 : SIGNAL_LOCK ();
2804 : 13 : mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, TRUE);
2805 [ + + ]: 13 : if (mlist)
2806 : : {
2807 : 2 : handler_seq_no = mlist->handler->sequential_number;
2808 : 2 : handler_match_free1_R (mlist, instance);
2809 : : }
2810 : 13 : SIGNAL_UNLOCK ();
2811 : : }
2812 : :
2813 : 13 : return handler_seq_no;
2814 : : }
2815 : :
2816 : : typedef void (*CallbackHandlerFunc) (gpointer instance, gulong handler_seq_no);
2817 : :
2818 : : static guint
2819 : 401998 : signal_handlers_foreach_matched_unlocked_R (gpointer instance,
2820 : : GSignalMatchType mask,
2821 : : guint signal_id,
2822 : : GQuark detail,
2823 : : GClosure *closure,
2824 : : gpointer func,
2825 : : gpointer data,
2826 : : CallbackHandlerFunc callback)
2827 : : {
2828 : : HandlerMatch *mlist;
2829 : 401998 : guint n_handlers = 0;
2830 : :
2831 : 401998 : mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, FALSE);
2832 [ + + ]: 803944 : while (mlist)
2833 : : {
2834 : 401946 : n_handlers++;
2835 [ + - ]: 401946 : if (mlist->handler->sequential_number)
2836 : 401946 : callback (instance, mlist->handler->sequential_number);
2837 : :
2838 : 401946 : mlist = handler_match_free1_R (mlist, instance);
2839 : : }
2840 : :
2841 : 401998 : return n_handlers;
2842 : : }
2843 : :
2844 : : /**
2845 : : * g_signal_handlers_block_matched:
2846 : : * @instance: (type GObject.Object): The instance to block handlers from.
2847 : : * @mask: Mask indicating which of @signal_id, @detail, @closure, @func
2848 : : * and/or @data the handlers have to match.
2849 : : * @signal_id: Signal the handlers have to be connected to.
2850 : : * @detail: Signal detail the handlers have to be connected to.
2851 : : * @closure: (nullable): The closure the handlers will invoke.
2852 : : * @func: The C closure callback of the handlers (useless for non-C closures).
2853 : : * @data: (nullable) (closure closure): The closure data of the handlers' closures.
2854 : : *
2855 : : * Blocks all handlers on an instance that match a certain selection criteria.
2856 : : *
2857 : : * The criteria mask is passed as a combination of #GSignalMatchType flags, and
2858 : : * the criteria values are passed as arguments. A handler must match on all
2859 : : * flags set in @mask to be blocked (i.e. the match is conjunctive).
2860 : : *
2861 : : * Passing at least one of the %G_SIGNAL_MATCH_ID, %G_SIGNAL_MATCH_CLOSURE,
2862 : : * %G_SIGNAL_MATCH_FUNC
2863 : : * or %G_SIGNAL_MATCH_DATA match flags is required for successful matches.
2864 : : * If no handlers were found, 0 is returned, the number of blocked handlers
2865 : : * otherwise.
2866 : : *
2867 : : * Support for %G_SIGNAL_MATCH_ID was added in GLib 2.78.
2868 : : *
2869 : : * Returns: The number of handlers that matched.
2870 : : */
2871 : : guint
2872 : 5 : g_signal_handlers_block_matched (gpointer instance,
2873 : : GSignalMatchType mask,
2874 : : guint signal_id,
2875 : : GQuark detail,
2876 : : GClosure *closure,
2877 : : gpointer func,
2878 : : gpointer data)
2879 : : {
2880 : 5 : guint n_handlers = 0;
2881 : :
2882 : 5 : g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
2883 : 5 : g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
2884 : :
2885 [ + - ]: 5 : if (mask & (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
2886 : : {
2887 : 5 : SIGNAL_LOCK ();
2888 : : n_handlers =
2889 : 5 : signal_handlers_foreach_matched_unlocked_R (instance, mask, signal_id, detail,
2890 : : closure, func, data,
2891 : : signal_handler_block_unlocked);
2892 : 5 : SIGNAL_UNLOCK ();
2893 : : }
2894 : :
2895 : 5 : return n_handlers;
2896 : : }
2897 : :
2898 : : /**
2899 : : * g_signal_handlers_unblock_matched:
2900 : : * @instance: (type GObject.Object): The instance to unblock handlers from.
2901 : : * @mask: Mask indicating which of @signal_id, @detail, @closure, @func
2902 : : * and/or @data the handlers have to match.
2903 : : * @signal_id: Signal the handlers have to be connected to.
2904 : : * @detail: Signal detail the handlers have to be connected to.
2905 : : * @closure: (nullable): The closure the handlers will invoke.
2906 : : * @func: The C closure callback of the handlers (useless for non-C closures).
2907 : : * @data: (nullable) (closure closure): The closure data of the handlers' closures.
2908 : : *
2909 : : * Unblocks all handlers on an instance that match a certain selection
2910 : : * criteria.
2911 : : *
2912 : : * The criteria mask is passed as a combination of #GSignalMatchType flags, and
2913 : : * the criteria values are passed as arguments. A handler must match on all
2914 : : * flags set in @mask to be unblocked (i.e. the match is conjunctive).
2915 : : *
2916 : : * Passing at least one of the %G_SIGNAL_MATCH_ID, %G_SIGNAL_MATCH_CLOSURE,
2917 : : * %G_SIGNAL_MATCH_FUNC
2918 : : * or %G_SIGNAL_MATCH_DATA match flags is required for successful matches.
2919 : : * If no handlers were found, 0 is returned, the number of unblocked handlers
2920 : : * otherwise. The match criteria should not apply to any handlers that are
2921 : : * not currently blocked.
2922 : : *
2923 : : * Support for %G_SIGNAL_MATCH_ID was added in GLib 2.78.
2924 : : *
2925 : : * Returns: The number of handlers that matched.
2926 : : */
2927 : : guint
2928 : 3 : g_signal_handlers_unblock_matched (gpointer instance,
2929 : : GSignalMatchType mask,
2930 : : guint signal_id,
2931 : : GQuark detail,
2932 : : GClosure *closure,
2933 : : gpointer func,
2934 : : gpointer data)
2935 : : {
2936 : 3 : guint n_handlers = 0;
2937 : :
2938 : 3 : g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
2939 : 3 : g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
2940 : :
2941 [ + - ]: 3 : if (mask & (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
2942 : : {
2943 : 3 : SIGNAL_LOCK ();
2944 : : n_handlers =
2945 : 3 : signal_handlers_foreach_matched_unlocked_R (instance, mask, signal_id, detail,
2946 : : closure, func, data,
2947 : : signal_handler_unblock_unlocked);
2948 : 3 : SIGNAL_UNLOCK ();
2949 : : }
2950 : :
2951 : 3 : return n_handlers;
2952 : : }
2953 : :
2954 : : /**
2955 : : * g_signal_handlers_disconnect_matched:
2956 : : * @instance: (type GObject.Object): The instance to remove handlers from.
2957 : : * @mask: Mask indicating which of @signal_id, @detail, @closure, @func
2958 : : * and/or @data the handlers have to match.
2959 : : * @signal_id: Signal the handlers have to be connected to.
2960 : : * @detail: Signal detail the handlers have to be connected to.
2961 : : * @closure: (nullable): The closure the handlers will invoke.
2962 : : * @func: The C closure callback of the handlers (useless for non-C closures).
2963 : : * @data: (nullable) (closure closure): The closure data of the handlers' closures.
2964 : : *
2965 : : * Disconnects all handlers on an instance that match a certain
2966 : : * selection criteria.
2967 : : *
2968 : : * The criteria mask is passed as a combination of #GSignalMatchType flags, and
2969 : : * the criteria values are passed as arguments. A handler must match on all
2970 : : * flags set in @mask to be disconnected (i.e. the match is conjunctive).
2971 : : *
2972 : : * Passing at least one of the %G_SIGNAL_MATCH_ID, %G_SIGNAL_MATCH_CLOSURE,
2973 : : * %G_SIGNAL_MATCH_FUNC or
2974 : : * %G_SIGNAL_MATCH_DATA match flags is required for successful
2975 : : * matches. If no handlers were found, 0 is returned, the number of
2976 : : * disconnected handlers otherwise.
2977 : : *
2978 : : * Support for %G_SIGNAL_MATCH_ID was added in GLib 2.78.
2979 : : *
2980 : : * Returns: The number of handlers that matched.
2981 : : */
2982 : : guint
2983 : 401461 : g_signal_handlers_disconnect_matched (gpointer instance,
2984 : : GSignalMatchType mask,
2985 : : guint signal_id,
2986 : : GQuark detail,
2987 : : GClosure *closure,
2988 : : gpointer func,
2989 : : gpointer data)
2990 : : {
2991 : 401461 : guint n_handlers = 0;
2992 : :
2993 : 401461 : g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
2994 : 401461 : g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
2995 : :
2996 [ + + ]: 401461 : if (mask & (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
2997 : : {
2998 : 401153 : SIGNAL_LOCK ();
2999 : : n_handlers =
3000 : 401990 : signal_handlers_foreach_matched_unlocked_R (instance, mask, signal_id, detail,
3001 : : closure, func, data,
3002 : : signal_handler_disconnect_unlocked);
3003 : 401990 : SIGNAL_UNLOCK ();
3004 : : }
3005 : :
3006 : 401740 : return n_handlers;
3007 : : }
3008 : :
3009 : : /**
3010 : : * g_signal_has_handler_pending:
3011 : : * @instance: (type GObject.Object): the object whose signal handlers are sought.
3012 : : * @signal_id: the signal id.
3013 : : * @detail: the detail.
3014 : : * @may_be_blocked: whether blocked handlers should count as match.
3015 : : *
3016 : : * Returns whether there are any handlers connected to @instance for the
3017 : : * given signal id and detail.
3018 : : *
3019 : : * If @detail is 0 then it will only match handlers that were connected
3020 : : * without detail. If @detail is non-zero then it will match handlers
3021 : : * connected both without detail and with the given detail. This is
3022 : : * consistent with how a signal emitted with @detail would be delivered
3023 : : * to those handlers.
3024 : : *
3025 : : * Since 2.46 this also checks for a non-default class closure being
3026 : : * installed, as this is basically always what you want.
3027 : : *
3028 : : * One example of when you might use this is when the arguments to the
3029 : : * signal are difficult to compute. A class implementor may opt to not
3030 : : * emit the signal if no one is attached anyway, thus saving the cost
3031 : : * of building the arguments.
3032 : : *
3033 : : * Returns: %TRUE if a handler is connected to the signal, %FALSE
3034 : : * otherwise.
3035 : : */
3036 : : gboolean
3037 : 111 : g_signal_has_handler_pending (gpointer instance,
3038 : : guint signal_id,
3039 : : GQuark detail,
3040 : : gboolean may_be_blocked)
3041 : : {
3042 : : HandlerMatch *mlist;
3043 : : gboolean has_pending;
3044 : : SignalNode *node;
3045 : :
3046 : 111 : g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
3047 : 111 : g_return_val_if_fail (signal_id > 0, FALSE);
3048 : :
3049 : 111 : SIGNAL_LOCK ();
3050 : :
3051 : 111 : node = LOOKUP_SIGNAL_NODE (signal_id);
3052 [ - + ]: 111 : if (detail)
3053 : : {
3054 [ # # ]: 0 : if (!(node->flags & G_SIGNAL_DETAILED))
3055 : : {
3056 : 0 : g_critical ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
3057 : 0 : SIGNAL_UNLOCK ();
3058 : 0 : return FALSE;
3059 : : }
3060 : : }
3061 [ + + ]: 111 : mlist = handlers_find (instance,
3062 : : (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | (may_be_blocked ? 0 : G_SIGNAL_MATCH_UNBLOCKED)),
3063 : : signal_id, detail, NULL, NULL, NULL, TRUE);
3064 [ + + ]: 111 : if (mlist)
3065 : : {
3066 : 67 : has_pending = TRUE;
3067 : 67 : handler_match_free1_R (mlist, instance);
3068 : : }
3069 : : else
3070 : : {
3071 : 44 : ClassClosure *class_closure = signal_find_class_closure (node, G_TYPE_FROM_INSTANCE (instance));
3072 [ + + - + ]: 44 : if (class_closure != NULL && class_closure->instance_type != 0)
3073 : 0 : has_pending = TRUE;
3074 : : else
3075 : 44 : has_pending = FALSE;
3076 : : }
3077 : 111 : SIGNAL_UNLOCK ();
3078 : :
3079 : 111 : return has_pending;
3080 : : }
3081 : :
3082 : : static void
3083 : : signal_emitv_unlocked (const GValue *instance_and_params,
3084 : : guint signal_id,
3085 : : GQuark detail,
3086 : : GValue *return_value);
3087 : :
3088 : : /**
3089 : : * g_signal_emitv:
3090 : : * @instance_and_params: (array): argument list for the signal emission.
3091 : : * The first element in the array is a #GValue for the instance the signal
3092 : : * is being emitted on. The rest are any arguments to be passed to the signal.
3093 : : * @signal_id: the signal id
3094 : : * @detail: the detail
3095 : : * @return_value: (inout) (optional): Location to
3096 : : * store the return value of the signal emission. This must be provided if the
3097 : : * specified signal returns a value, but may be ignored otherwise.
3098 : : *
3099 : : * Emits a signal. Signal emission is done synchronously.
3100 : : * The method will only return control after all handlers are called or signal emission was stopped.
3101 : : *
3102 : : * Note that g_signal_emitv() doesn't change @return_value if no handlers are
3103 : : * connected, in contrast to g_signal_emit() and g_signal_emit_valist().
3104 : : */
3105 : : void
3106 : 50 : g_signal_emitv (const GValue *instance_and_params,
3107 : : guint signal_id,
3108 : : GQuark detail,
3109 : : GValue *return_value)
3110 : : {
3111 : 50 : SIGNAL_LOCK ();
3112 : 50 : signal_emitv_unlocked (instance_and_params, signal_id, detail, return_value);
3113 : 50 : SIGNAL_UNLOCK ();
3114 : 50 : }
3115 : :
3116 : : static void
3117 : 50 : signal_emitv_unlocked (const GValue *instance_and_params,
3118 : : guint signal_id,
3119 : : GQuark detail,
3120 : : GValue *return_value)
3121 : : {
3122 : : gpointer instance;
3123 : : SignalNode *node;
3124 : : #ifdef G_ENABLE_DEBUG
3125 : : const GValue *param_values;
3126 : : guint i;
3127 : : #endif
3128 : :
3129 : 52 : g_return_if_fail (instance_and_params != NULL);
3130 : 50 : instance = g_value_peek_pointer (instance_and_params);
3131 : 50 : g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
3132 : 50 : g_return_if_fail (signal_id > 0);
3133 : :
3134 : : #ifdef G_ENABLE_DEBUG
3135 : 50 : param_values = instance_and_params + 1;
3136 : : #endif
3137 : :
3138 : 50 : node = LOOKUP_SIGNAL_NODE (signal_id);
3139 [ + - + + : 50 : if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
- + ]
3140 : : {
3141 : 0 : g_critical ("%s: signal id '%u' is invalid for instance '%p'", G_STRLOC, signal_id, instance);
3142 : 0 : return;
3143 : : }
3144 : : #ifdef G_ENABLE_DEBUG
3145 [ - + - - ]: 50 : if (detail && !(node->flags & G_SIGNAL_DETAILED))
3146 : : {
3147 : 0 : g_critical ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
3148 : 0 : return;
3149 : : }
3150 [ + + ]: 219 : for (i = 0; i < node->n_params; i++)
3151 [ - + + - : 169 : if (!G_TYPE_CHECK_VALUE_TYPE (param_values + i, node->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE))
- + ]
3152 : : {
3153 : 0 : g_critical ("%s: value for '%s' parameter %u for signal \"%s\" is of type '%s'",
3154 : : G_STRLOC,
3155 : : type_debug_name (node->param_types[i]),
3156 : : i,
3157 : : node->name,
3158 : : G_VALUE_TYPE_NAME (param_values + i));
3159 : 0 : return;
3160 : : }
3161 [ + + ]: 50 : if (node->return_type != G_TYPE_NONE)
3162 : : {
3163 [ + + ]: 39 : if (!return_value)
3164 : : {
3165 : 1 : g_critical ("%s: return value '%s' for signal \"%s\" is (NULL)",
3166 : : G_STRLOC,
3167 : : type_debug_name (node->return_type),
3168 : : node->name);
3169 : 1 : return;
3170 : : }
3171 [ + + - + : 38 : else if (!node->accumulator && !G_TYPE_CHECK_VALUE_TYPE (return_value, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE))
+ + + + ]
3172 : : {
3173 : 1 : g_critical ("%s: return value '%s' for signal \"%s\" is of type '%s'",
3174 : : G_STRLOC,
3175 : : type_debug_name (node->return_type),
3176 : : node->name,
3177 : : G_VALUE_TYPE_NAME (return_value));
3178 : 1 : return;
3179 : : }
3180 : : }
3181 : : else
3182 : 11 : return_value = NULL;
3183 : : #endif /* G_ENABLE_DEBUG */
3184 : :
3185 : : /* optimize NOP emissions */
3186 [ + + ]: 48 : if (!node->single_va_closure_is_valid)
3187 : 34 : node_update_single_va_closure (node);
3188 : :
3189 [ - + ]: 48 : if (node->single_va_closure != NULL &&
3190 [ # # # # ]: 0 : (node->single_va_closure == SINGLE_VA_CLOSURE_EMPTY_MAGIC ||
3191 : 0 : _g_closure_is_void (node->single_va_closure, instance)))
3192 : : {
3193 : : HandlerList* hlist;
3194 : :
3195 : : /* single_va_closure is only true for GObjects, so fast path if no handler ever connected to the signal */
3196 [ # # ]: 0 : if (_g_object_has_signal_handler ((GObject *)instance))
3197 : 0 : hlist = handler_list_lookup (node->signal_id, instance);
3198 : : else
3199 : 0 : hlist = NULL;
3200 : :
3201 [ # # # # ]: 0 : if (hlist == NULL || hlist->handlers == NULL)
3202 : : {
3203 : : /* nothing to do to emit this signal */
3204 : : /* g_printerr ("omitting emission of \"%s\"\n", node->name); */
3205 : 0 : return;
3206 : : }
3207 : : }
3208 : :
3209 : : /* Pass a stable node pointer, whose address can't change even if the
3210 : : * g_signal_nodes array gets reallocated. */
3211 : 48 : SignalNode node_copy = *node;
3212 : 48 : signal_emit_unlocked_R (&node_copy, detail, instance, return_value, instance_and_params);
3213 : : }
3214 : :
3215 : : static inline gboolean
3216 : 27394870 : accumulate (GSignalInvocationHint *ihint,
3217 : : GValue *return_accu,
3218 : : GValue *handler_return,
3219 : : SignalAccumulator *accumulator)
3220 : : {
3221 : : gboolean continue_emission;
3222 : :
3223 [ + # ]: 27394870 : if (!accumulator)
3224 : 27400251 : return TRUE;
3225 : :
3226 : 0 : continue_emission = accumulator->func (ihint, return_accu, handler_return, accumulator->data);
3227 : 2311 : g_value_reset (handler_return);
3228 : :
3229 : 2311 : ihint->run_type &= ~G_SIGNAL_ACCUMULATOR_FIRST_RUN;
3230 : :
3231 : 2311 : return continue_emission;
3232 : : }
3233 : :
3234 : : static gboolean
3235 : : signal_emit_valist_unlocked (gpointer instance,
3236 : : guint signal_id,
3237 : : GQuark detail,
3238 : : va_list var_args);
3239 : :
3240 : : /**
3241 : : * g_signal_emit_valist: (skip)
3242 : : * @instance: (type GObject.TypeInstance): the instance the signal is being
3243 : : * emitted on.
3244 : : * @signal_id: the signal id
3245 : : * @detail: the detail
3246 : : * @var_args: a list of parameters to be passed to the signal, followed by a
3247 : : * location for the return value. If the return type of the signal
3248 : : * is %G_TYPE_NONE, the return value location can be omitted.
3249 : : *
3250 : : * Emits a signal. Signal emission is done synchronously.
3251 : : * The method will only return control after all handlers are called or signal emission was stopped.
3252 : : *
3253 : : * Note that g_signal_emit_valist() resets the return value to the default
3254 : : * if no handlers are connected, in contrast to g_signal_emitv().
3255 : : */
3256 : : void
3257 : 36856534 : g_signal_emit_valist (gpointer instance,
3258 : : guint signal_id,
3259 : : GQuark detail,
3260 : : va_list var_args)
3261 : : {
3262 : 36856534 : SIGNAL_LOCK ();
3263 [ + + ]: 36876840 : if (signal_emit_valist_unlocked (instance, signal_id, detail, var_args))
3264 : 19761491 : SIGNAL_UNLOCK ();
3265 : 36863738 : }
3266 : :
3267 : : /*<private>
3268 : : * signal_emit_valist_unlocked:
3269 : : * @instance: The instance to emit from
3270 : : * @signal_id: Signal id to emit
3271 : : * @detail: Signal detail
3272 : : * @var_args: Call arguments
3273 : : *
3274 : : * Returns: %TRUE if the signal mutex has been left locked
3275 : : */
3276 : : static gboolean
3277 : 36877253 : signal_emit_valist_unlocked (gpointer instance,
3278 : : guint signal_id,
3279 : : GQuark detail,
3280 : : va_list var_args)
3281 : : {
3282 : : GValue *instance_and_params;
3283 : : GValue *param_values;
3284 : : SignalNode *node;
3285 : : guint i;
3286 : :
3287 : 36877253 : g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), TRUE);
3288 : 36877253 : g_return_val_if_fail (signal_id > 0, TRUE);
3289 : :
3290 : 36877253 : node = LOOKUP_SIGNAL_NODE (signal_id);
3291 [ + - + + : 36877253 : if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
- + ]
3292 : : {
3293 : 0 : g_critical ("%s: signal id '%u' is invalid for instance '%p'", G_STRLOC, signal_id, instance);
3294 : 0 : return TRUE;
3295 : : }
3296 : : #ifndef G_DISABLE_CHECKS
3297 [ + + - + ]: 36877253 : if (detail && !(node->flags & G_SIGNAL_DETAILED))
3298 : : {
3299 : 0 : g_critical ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
3300 : 0 : return TRUE;
3301 : : }
3302 : : #endif /* !G_DISABLE_CHECKS */
3303 : :
3304 [ + + ]: 36877253 : if (!node->single_va_closure_is_valid)
3305 : 438 : node_update_single_va_closure (node);
3306 : :
3307 : : /* There's no need to deep copy this, because a SignalNode instance won't
3308 : : * ever be destroyed, given that _g_signals_destroy() is not called in any
3309 : : * real program, however the SignalNode pointer could change, so just store
3310 : : * the struct contents references, so that we won't try to deference a
3311 : : * potentially invalid (or changed) pointer;
3312 : : */
3313 : 36877253 : SignalNode node_copy = *node;
3314 : :
3315 [ + + ]: 36877253 : if (node->single_va_closure != NULL)
3316 : : {
3317 : : HandlerList* hlist;
3318 : 36774690 : Handler *fastpath_handler = NULL;
3319 : : Handler *l;
3320 : 36774690 : GClosure *closure = NULL;
3321 : 36774690 : gboolean fastpath = TRUE;
3322 : 36774690 : GSignalFlags run_type = G_SIGNAL_RUN_FIRST;
3323 : :
3324 [ + + + + ]: 73218973 : if (node->single_va_closure != SINGLE_VA_CLOSURE_EMPTY_MAGIC &&
3325 : 36444283 : !_g_closure_is_void (node->single_va_closure, instance))
3326 : : {
3327 [ + + ]: 9352832 : if (_g_closure_supports_invoke_va (node->single_va_closure))
3328 : : {
3329 : 141858 : closure = node->single_va_closure;
3330 [ + + ]: 141858 : if (node->single_va_closure_is_after)
3331 : 1859 : run_type = G_SIGNAL_RUN_LAST;
3332 : : else
3333 : 139999 : run_type = G_SIGNAL_RUN_FIRST;
3334 : : }
3335 : : else
3336 : 9210974 : fastpath = FALSE;
3337 : : }
3338 : :
3339 : : /* single_va_closure is only true for GObjects, so fast path if no handler ever connected to the signal */
3340 [ + + ]: 36774690 : if (_g_object_has_signal_handler ((GObject *)instance))
3341 : 12117673 : hlist = handler_list_lookup (node->signal_id, instance);
3342 : : else
3343 : 24657017 : hlist = NULL;
3344 : :
3345 [ + + + + : 41689318 : for (l = hlist ? hlist->handlers : NULL; fastpath && l != NULL; l = l->next)
+ + ]
3346 : : {
3347 [ + + ]: 7858607 : if (!l->block_count &&
3348 [ + + + + ]: 7858324 : (!l->detail || l->detail == detail))
3349 : : {
3350 [ + + + + ]: 7730562 : if (closure != NULL || !_g_closure_supports_invoke_va (l->closure))
3351 : : {
3352 : 2943979 : fastpath = FALSE;
3353 : 2943979 : break;
3354 : : }
3355 : : else
3356 : : {
3357 : 4786583 : fastpath_handler = l;
3358 : 4786583 : closure = l->closure;
3359 [ - + ]: 4786583 : if (l->after)
3360 : 0 : run_type = G_SIGNAL_RUN_LAST;
3361 : : else
3362 : 4786583 : run_type = G_SIGNAL_RUN_FIRST;
3363 : : }
3364 : : }
3365 : : }
3366 : :
3367 [ + + + + : 36774690 : if (fastpath && closure == NULL && node_copy.return_type == G_TYPE_NONE)
+ - ]
3368 : 19761648 : return TRUE;
3369 : :
3370 : : /* Don't allow no-recurse emission as we might have to restart, which means
3371 : : we will run multiple handlers and thus must ref all arguments */
3372 [ + + + + ]: 17013042 : if (closure != NULL && (node_copy.flags & (G_SIGNAL_NO_RECURSE)) != 0)
3373 : 4616971 : fastpath = FALSE;
3374 : :
3375 [ + + ]: 17013042 : if (fastpath)
3376 : : {
3377 : : Emission emission;
3378 : 241137 : GValue *return_accu, accu = G_VALUE_INIT;
3379 : 241137 : GType instance_type = G_TYPE_FROM_INSTANCE (instance);
3380 : 241137 : GValue emission_return = G_VALUE_INIT;
3381 : 241137 : GType rtype = node_copy.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE;
3382 : 241137 : gboolean static_scope = node_copy.return_type & G_SIGNAL_TYPE_STATIC_SCOPE;
3383 : :
3384 [ + + ]: 241137 : if (rtype == G_TYPE_NONE)
3385 : 240255 : return_accu = NULL;
3386 [ + + ]: 882 : else if (node_copy.accumulator)
3387 : 867 : return_accu = &accu;
3388 : : else
3389 : 15 : return_accu = &emission_return;
3390 : :
3391 : 241137 : emission.instance = instance;
3392 : 241137 : emission.ihint.signal_id = signal_id;
3393 : 241137 : emission.ihint.detail = detail;
3394 : 241137 : emission.ihint.run_type = run_type | G_SIGNAL_ACCUMULATOR_FIRST_RUN;
3395 : 241137 : emission.state = EMISSION_RUN;
3396 : 241137 : emission.chain_type = instance_type;
3397 : 241137 : emission_push (&emission);
3398 : :
3399 [ + + ]: 241137 : if (fastpath_handler)
3400 : 169703 : handler_ref (fastpath_handler);
3401 : :
3402 [ + - ]: 241137 : if (closure != NULL)
3403 : : {
3404 : 241137 : TRACE(GOBJECT_SIGNAL_EMIT(signal_id, detail, instance, instance_type));
3405 : :
3406 : 241137 : SIGNAL_UNLOCK ();
3407 : :
3408 [ + + ]: 241137 : if (rtype != G_TYPE_NONE)
3409 : 882 : g_value_init (&emission_return, rtype);
3410 : :
3411 [ + + ]: 241137 : if (node_copy.accumulator)
3412 : 867 : g_value_init (&accu, rtype);
3413 : :
3414 : : /*
3415 : : * Coverity doesn’t understand the paired ref/unref here and seems
3416 : : * to ignore the ref, thus reports every call to g_signal_emit()
3417 : : * as causing a double-free. That’s incorrect, but I can’t get a
3418 : : * model file to work for avoiding the false positives, so instead
3419 : : * comment out the ref/unref when doing static analysis.
3420 : : */
3421 : : #ifndef __COVERITY__
3422 : 241137 : g_object_ref (instance);
3423 : : #endif
3424 : 241137 : _g_closure_invoke_va (closure,
3425 : : return_accu,
3426 : : instance,
3427 : : var_args,
3428 : 241137 : node_copy.n_params,
3429 : : node_copy.param_types);
3430 : 241135 : accumulate (&emission.ihint, &emission_return, &accu, node_copy.accumulator);
3431 : :
3432 [ + + ]: 241135 : if (node_copy.accumulator)
3433 : 867 : g_value_unset (&accu);
3434 : :
3435 : 241135 : SIGNAL_LOCK ();
3436 : : }
3437 : :
3438 : 241135 : emission.chain_type = G_TYPE_NONE;
3439 : 241135 : emission_pop (&emission);
3440 : :
3441 [ + + ]: 241135 : if (fastpath_handler)
3442 : 169701 : handler_unref_R (signal_id, instance, fastpath_handler);
3443 : :
3444 : 241135 : SIGNAL_UNLOCK ();
3445 : :
3446 [ + + ]: 241135 : if (rtype != G_TYPE_NONE)
3447 : : {
3448 : 882 : gchar *error = NULL;
3449 [ + + ]: 2348 : for (i = 0; i < node_copy.n_params; i++)
3450 : : {
3451 : 1466 : GType ptype = node_copy.param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE;
3452 [ + - - - : 2932 : G_VALUE_COLLECT_SKIP (ptype, var_args);
+ - + + ]
3453 : : }
3454 : :
3455 [ - + ]: 882 : if (closure == NULL)
3456 : 0 : g_value_init (&emission_return, rtype);
3457 : :
3458 [ - + - - : 1764 : G_VALUE_LCOPY (&emission_return,
- - + - +
+ ]
3459 : : var_args,
3460 : : static_scope ? G_VALUE_NOCOPY_CONTENTS : 0,
3461 : : &error);
3462 [ + - ]: 882 : if (!error)
3463 : 882 : g_value_unset (&emission_return);
3464 : : else
3465 : : {
3466 : 0 : g_critical ("%s: %s", G_STRLOC, error);
3467 : 0 : g_free (error);
3468 : : /* we purposely leak the value here, it might not be
3469 : : * in a correct state if an error condition occurred
3470 : : */
3471 : : }
3472 : : }
3473 : :
3474 : 241135 : TRACE(GOBJECT_SIGNAL_EMIT_END(signal_id, detail, instance, instance_type));
3475 : :
3476 : : /* See comment above paired ref above */
3477 : : #ifndef __COVERITY__
3478 [ + - ]: 241135 : if (closure != NULL)
3479 : 241135 : g_object_unref (instance);
3480 : : #endif
3481 : :
3482 : 241135 : return FALSE;
3483 : : }
3484 : : }
3485 : :
3486 : 16874468 : SIGNAL_UNLOCK ();
3487 : :
3488 [ + # ]: 16873543 : instance_and_params = g_newa0 (GValue, node_copy.n_params + 1);
3489 : 16873543 : param_values = instance_and_params + 1;
3490 : :
3491 [ + + ]: 33697048 : for (i = 0; i < node_copy.n_params; i++)
3492 : : {
3493 : : gchar *error;
3494 : 16825790 : GType ptype = node_copy.param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE;
3495 : 16825790 : gboolean static_scope = node_copy.param_types[i] & G_SIGNAL_TYPE_STATIC_SCOPE;
3496 : :
3497 [ + + + + : 33650052 : G_VALUE_COLLECT_INIT (param_values + i, ptype,
+ + + - +
+ ]
3498 : : var_args,
3499 : : static_scope ? G_VALUE_NOCOPY_CONTENTS : 0,
3500 : : &error);
3501 [ + + ]: 16823671 : if (error)
3502 : : {
3503 : 166 : g_critical ("%s: %s", G_STRLOC, error);
3504 : 0 : g_free (error);
3505 : :
3506 : : /* we purposely leak the value here, it might not be
3507 : : * in a correct state if an error condition occurred
3508 : : */
3509 [ # # ]: 0 : while (i--)
3510 : 0 : g_value_unset (param_values + i);
3511 : :
3512 : 0 : return FALSE;
3513 : : }
3514 : : }
3515 : :
3516 : 16871258 : g_value_init_from_instance (instance_and_params, instance);
3517 [ + + ]: 16870526 : if (node_copy.return_type == G_TYPE_NONE)
3518 : : {
3519 : 13661656 : SIGNAL_LOCK ();
3520 : 13662550 : signal_emit_unlocked_R (&node_copy, detail, instance, NULL, instance_and_params);
3521 : 13662544 : SIGNAL_UNLOCK ();
3522 : : }
3523 : : else
3524 : : {
3525 : 3208870 : GValue return_value = G_VALUE_INIT;
3526 : 3208870 : gchar *error = NULL;
3527 : 3208870 : GType rtype = node_copy.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE;
3528 : 3208870 : gboolean static_scope = node_copy.return_type & G_SIGNAL_TYPE_STATIC_SCOPE;
3529 : :
3530 : 3208870 : g_value_init (&return_value, rtype);
3531 : :
3532 : 3206053 : SIGNAL_LOCK ();
3533 : 3211918 : signal_emit_unlocked_R (&node_copy, detail, instance, &return_value, instance_and_params);
3534 : 3211918 : SIGNAL_UNLOCK ();
3535 : :
3536 [ - + - - : 6419338 : G_VALUE_LCOPY (&return_value,
- - + - +
+ ]
3537 : : var_args,
3538 : : static_scope ? G_VALUE_NOCOPY_CONTENTS : 0,
3539 : : &error);
3540 [ + + ]: 3211146 : if (!error)
3541 : 3211097 : g_value_unset (&return_value);
3542 : : else
3543 : : {
3544 : 49 : g_critical ("%s: %s", G_STRLOC, error);
3545 : 0 : g_free (error);
3546 : :
3547 : : /* we purposely leak the value here, it might not be
3548 : : * in a correct state if an error condition occurred
3549 : : */
3550 : : }
3551 : : }
3552 [ + + ]: 33674636 : for (i = 0; i < node_copy.n_params; i++)
3553 : 16818349 : g_value_unset (param_values + i);
3554 : 16856287 : g_value_unset (instance_and_params);
3555 : :
3556 : 16863159 : return FALSE;
3557 : : }
3558 : :
3559 : : /**
3560 : : * g_signal_emit:
3561 : : * @instance: (type GObject.Object): the instance the signal is being emitted on.
3562 : : * @signal_id: the signal id
3563 : : * @detail: the detail
3564 : : * @...: parameters to be passed to the signal, followed by a
3565 : : * location for the return value. If the return type of the signal
3566 : : * is %G_TYPE_NONE, the return value location can be omitted.
3567 : : *
3568 : : * Emits a signal. Signal emission is done synchronously.
3569 : : * The method will only return control after all handlers are called or signal emission was stopped.
3570 : : *
3571 : : * Note that g_signal_emit() resets the return value to the default
3572 : : * if no handlers are connected, in contrast to g_signal_emitv().
3573 : : */
3574 : : void
3575 : 36862318 : g_signal_emit (gpointer instance,
3576 : : guint signal_id,
3577 : : GQuark detail,
3578 : : ...)
3579 : : {
3580 : : va_list var_args;
3581 : :
3582 : 36862318 : va_start (var_args, detail);
3583 : 36862318 : g_signal_emit_valist (instance, signal_id, detail, var_args);
3584 : 36862991 : va_end (var_args);
3585 : 36862991 : }
3586 : :
3587 : : /**
3588 : : * g_signal_emit_by_name:
3589 : : * @instance: (type GObject.Object): the instance the signal is being emitted on.
3590 : : * @detailed_signal: a string of the form "signal-name::detail".
3591 : : * @...: parameters to be passed to the signal, followed by a
3592 : : * location for the return value. If the return type of the signal
3593 : : * is %G_TYPE_NONE, the return value location can be omitted. The
3594 : : * number of parameters to pass to this function is defined when creating the signal.
3595 : : *
3596 : : * Emits a signal. Signal emission is done synchronously.
3597 : : * The method will only return control after all handlers are called or signal emission was stopped.
3598 : : *
3599 : : * Note that g_signal_emit_by_name() resets the return value to the default
3600 : : * if no handlers are connected, in contrast to g_signal_emitv().
3601 : : */
3602 : : void
3603 : 413 : g_signal_emit_by_name (gpointer instance,
3604 : : const gchar *detailed_signal,
3605 : : ...)
3606 : : {
3607 : 413 : GQuark detail = 0;
3608 : : guint signal_id;
3609 : : GType itype;
3610 : :
3611 : 413 : g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
3612 : 413 : g_return_if_fail (detailed_signal != NULL);
3613 : :
3614 : 413 : itype = G_TYPE_FROM_INSTANCE (instance);
3615 : :
3616 : 413 : SIGNAL_LOCK ();
3617 : 413 : signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
3618 : :
3619 [ + - ]: 413 : if (signal_id)
3620 : : {
3621 : : va_list var_args;
3622 : :
3623 : 413 : va_start (var_args, detailed_signal);
3624 [ + + ]: 413 : if (signal_emit_valist_unlocked (instance, signal_id, detail, var_args))
3625 : 157 : SIGNAL_UNLOCK ();
3626 : 413 : va_end (var_args);
3627 : : }
3628 : : else
3629 : : {
3630 : 0 : SIGNAL_UNLOCK ();
3631 : :
3632 : 0 : g_critical ("%s: signal name '%s' is invalid for instance '%p' of type '%s'",
3633 : : G_STRLOC, detailed_signal, instance, g_type_name (itype));
3634 : : }
3635 : : }
3636 : :
3637 : : G_ALWAYS_INLINE static inline GValue *
3638 : : maybe_init_accumulator_unlocked (SignalNode *node,
3639 : : GValue *emission_return,
3640 : : GValue *accumulator_value)
3641 : : {
3642 [ + + + + : 27163232 : if (node->accumulator)
+ + + + ]
3643 : : {
3644 [ - + + + : 1440 : if (accumulator_value->g_type)
+ + + - ]
3645 : 563 : return accumulator_value;
3646 : :
3647 : 877 : g_value_init (accumulator_value,
3648 : 877 : node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
3649 : 877 : return accumulator_value;
3650 : : }
3651 : :
3652 : 27161792 : return emission_return;
3653 : : }
3654 : :
3655 : : static gboolean
3656 : 16874516 : signal_emit_unlocked_R (SignalNode *node,
3657 : : GQuark detail,
3658 : : gpointer instance,
3659 : : GValue *emission_return,
3660 : : const GValue *instance_and_params)
3661 : : {
3662 : : SignalAccumulator *accumulator;
3663 : : Emission emission;
3664 : : GClosure *class_closure;
3665 : : HandlerList *hlist;
3666 : 16874516 : Handler *handler_list = NULL;
3667 : 16874516 : GValue *return_accu, accu = G_VALUE_INIT;
3668 : : guint signal_id;
3669 : : gulong max_sequential_handler_number;
3670 : 16874516 : gboolean return_value_altered = FALSE;
3671 : : guint n_params;
3672 : :
3673 : 16874516 : TRACE(GOBJECT_SIGNAL_EMIT(node->signal_id, detail, instance, G_TYPE_FROM_INSTANCE (instance)));
3674 : :
3675 : : /* We expect this function to be called with a stable SignalNode pointer
3676 : : * that cannot change location, so accessing its stable members should
3677 : : * always work even after a lock/unlock.
3678 : : */
3679 : 16874516 : signal_id = node->signal_id;
3680 : 16874516 : n_params = node->n_params + 1;
3681 : :
3682 [ + + ]: 16874516 : if (node->flags & G_SIGNAL_NO_RECURSE)
3683 : : {
3684 : 4616971 : Emission *emission_node = emission_find (signal_id, detail, instance);
3685 : :
3686 [ + + ]: 4616971 : if (emission_node)
3687 : : {
3688 : 67861 : emission_node->state = EMISSION_RESTART;
3689 : 67861 : return return_value_altered;
3690 : : }
3691 : : }
3692 : 16806655 : accumulator = node->accumulator;
3693 : 16806655 : emission.instance = instance;
3694 : 16806655 : emission.ihint.signal_id = node->signal_id;
3695 : 16806655 : emission.ihint.detail = detail;
3696 : 16806655 : emission.ihint.run_type = 0;
3697 : 16806655 : emission.state = 0;
3698 : 16806655 : emission.chain_type = G_TYPE_NONE;
3699 : 16806655 : emission_push (&emission);
3700 : 16806655 : class_closure = signal_lookup_closure (node, instance);
3701 : :
3702 : 39291 : EMIT_RESTART:
3703 : :
3704 [ + + ]: 16845946 : if (handler_list)
3705 : 39291 : handler_unref_R (signal_id, instance, handler_list);
3706 : 16845946 : max_sequential_handler_number = g_handler_sequential_number;
3707 : 16845946 : hlist = handler_list_lookup (signal_id, instance);
3708 [ + + ]: 16845946 : handler_list = hlist ? hlist->handlers : NULL;
3709 [ + + ]: 16845946 : if (handler_list)
3710 : 10359506 : handler_ref (handler_list);
3711 : :
3712 : 16845946 : emission.ihint.run_type = G_SIGNAL_RUN_FIRST | G_SIGNAL_ACCUMULATOR_FIRST_RUN;
3713 : :
3714 [ + + + + ]: 16845946 : if ((node->flags & G_SIGNAL_RUN_FIRST) && class_closure)
3715 : : {
3716 : 4987759 : emission.state = EMISSION_RUN;
3717 : :
3718 : 4987759 : emission.chain_type = G_TYPE_FROM_INSTANCE (instance);
3719 : 4987759 : SIGNAL_UNLOCK ();
3720 : 4987712 : return_accu = maybe_init_accumulator_unlocked (node, emission_return, &accu);
3721 : 4987712 : g_closure_invoke (class_closure,
3722 : : return_accu,
3723 : : n_params,
3724 : : instance_and_params,
3725 : : &emission.ihint);
3726 [ - + ]: 4987707 : if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) &&
3727 [ # # ]: 0 : emission.state == EMISSION_RUN)
3728 : 0 : emission.state = EMISSION_STOP;
3729 : 4987680 : SIGNAL_LOCK ();
3730 : 4987759 : emission.chain_type = G_TYPE_NONE;
3731 : 4987759 : return_value_altered = TRUE;
3732 : :
3733 [ - + ]: 4987759 : if (emission.state == EMISSION_STOP)
3734 : 0 : goto EMIT_CLEANUP;
3735 [ + + ]: 4987759 : else if (emission.state == EMISSION_RESTART)
3736 : 17549 : goto EMIT_RESTART;
3737 : : }
3738 : :
3739 [ + + ]: 16828397 : if (node->emission_hooks)
3740 : : {
3741 : : GHook *hook;
3742 : : GHook *static_emission_hooks[3];
3743 : 14 : size_t n_emission_hooks = 0;
3744 : 14 : const gboolean may_recurse = TRUE;
3745 : : guint i;
3746 : :
3747 : 14 : emission.state = EMISSION_HOOK;
3748 : :
3749 : : /* Quick check to determine whether any hooks match this emission,
3750 : : * before committing to the more complex work of calling those hooks.
3751 : : * We save a few of them into a static array, to try to avoid further
3752 : : * allocations.
3753 : : */
3754 : 14 : hook = g_hook_first_valid (node->emission_hooks, may_recurse);
3755 [ + + ]: 51 : while (hook)
3756 : : {
3757 : 37 : SignalHook *signal_hook = SIGNAL_HOOK (hook);
3758 : :
3759 [ - + - - ]: 37 : if (!signal_hook->detail || signal_hook->detail == detail)
3760 : : {
3761 [ + + ]: 37 : if (n_emission_hooks < G_N_ELEMENTS (static_emission_hooks))
3762 : : {
3763 : 16 : static_emission_hooks[n_emission_hooks] =
3764 : 16 : g_hook_ref (node->emission_hooks, hook);
3765 : : }
3766 : :
3767 : 37 : n_emission_hooks += 1;
3768 : : }
3769 : :
3770 : 37 : hook = g_hook_next_valid (node->emission_hooks, hook, may_recurse);
3771 : : }
3772 : :
3773 : : /* Re-iterate back through the matching hooks and copy them into
3774 : : * an array which won’t change when we unlock to call the
3775 : : * user-provided hook functions.
3776 : : * These functions may change hook configuration for this signal,
3777 : : * add / remove signal handlers, etc.
3778 : : */
3779 [ + + ]: 14 : if G_UNLIKELY (n_emission_hooks > 0)
3780 : : {
3781 : : guint8 static_hook_returns[G_N_ELEMENTS (static_emission_hooks)];
3782 : 10 : GHook **emission_hooks = NULL;
3783 : 10 : guint8 *hook_returns = NULL;
3784 : :
3785 [ + + ]: 10 : if G_LIKELY (n_emission_hooks <= G_N_ELEMENTS (static_emission_hooks))
3786 : : {
3787 : 7 : emission_hooks = static_emission_hooks;
3788 : 7 : hook_returns = static_hook_returns;
3789 : : }
3790 : : else
3791 : : {
3792 : 3 : emission_hooks = g_newa (GHook *, n_emission_hooks);
3793 : 3 : hook_returns = g_newa (guint8, n_emission_hooks);
3794 : :
3795 : : /* We can't just memcpy the ones we have in the static array,
3796 : : * to the alloca()'d one because otherwise we'd get an invalid
3797 : : * ID assertion during unref
3798 : : */
3799 : 3 : i = 0;
3800 : 3 : for (hook = g_hook_first_valid (node->emission_hooks, may_recurse);
3801 [ + + ]: 33 : hook != NULL;
3802 : 30 : hook = g_hook_next_valid (node->emission_hooks, hook, may_recurse))
3803 : : {
3804 : 30 : SignalHook *signal_hook = SIGNAL_HOOK (hook);
3805 : :
3806 [ - + - - ]: 30 : if (!signal_hook->detail || signal_hook->detail == detail)
3807 : : {
3808 [ + + ]: 30 : if (i < G_N_ELEMENTS (static_emission_hooks))
3809 : : {
3810 : 9 : emission_hooks[i] = g_steal_pointer (&static_emission_hooks[i]);
3811 : 9 : g_assert (emission_hooks[i] == hook);
3812 : : }
3813 : : else
3814 : : {
3815 : 21 : emission_hooks[i] = g_hook_ref (node->emission_hooks, hook);
3816 : : }
3817 : :
3818 : 30 : i += 1;
3819 : : }
3820 : : }
3821 : :
3822 : 3 : g_assert (i == n_emission_hooks);
3823 : : }
3824 : :
3825 : 10 : SIGNAL_UNLOCK ();
3826 : :
3827 [ + + ]: 47 : for (i = 0; i < n_emission_hooks; ++i)
3828 : : {
3829 : : GSignalEmissionHook hook_func;
3830 : : gboolean need_destroy;
3831 : : guint old_flags;
3832 : :
3833 : 37 : hook = emission_hooks[i];
3834 : 37 : hook_func = (GSignalEmissionHook) hook->func;
3835 : :
3836 : 37 : old_flags = g_atomic_int_or (&hook->flags, G_HOOK_FLAG_IN_CALL);
3837 : 37 : need_destroy = !hook_func (&emission.ihint, n_params,
3838 : : instance_and_params, hook->data);
3839 : :
3840 [ + - ]: 37 : if (!(old_flags & G_HOOK_FLAG_IN_CALL))
3841 : : {
3842 : 37 : g_atomic_int_compare_and_exchange (&hook->flags,
3843 : : old_flags | G_HOOK_FLAG_IN_CALL,
3844 : : old_flags);
3845 : : }
3846 : :
3847 : 37 : hook_returns[i] = !!need_destroy;
3848 : : }
3849 : :
3850 : 10 : SIGNAL_LOCK ();
3851 : :
3852 [ + + ]: 47 : for (i = 0; i < n_emission_hooks; i++)
3853 : : {
3854 : 37 : hook = emission_hooks[i];
3855 : :
3856 : 37 : g_hook_unref (node->emission_hooks, hook);
3857 : :
3858 [ + + ]: 37 : if (hook_returns[i])
3859 : 11 : g_hook_destroy_link (node->emission_hooks, hook);
3860 : : }
3861 : : }
3862 : :
3863 [ - + ]: 14 : if (emission.state == EMISSION_RESTART)
3864 : 0 : goto EMIT_RESTART;
3865 : : }
3866 : :
3867 [ + + ]: 16828397 : if (handler_list)
3868 : : {
3869 : 10341957 : Handler *handler = handler_list;
3870 : :
3871 : 10341957 : emission.state = EMISSION_RUN;
3872 : 10341957 : handler_ref (handler);
3873 : : do
3874 : : {
3875 : : Handler *tmp;
3876 : :
3877 [ + + ]: 10470599 : if (handler->after)
3878 : : {
3879 : 24 : handler_unref_R (signal_id, instance, handler_list);
3880 : 24 : handler_list = handler;
3881 : 24 : break;
3882 : : }
3883 [ + - + + : 10470575 : else if (!handler->block_count && (!handler->detail || handler->detail == detail) &&
+ + ]
3884 [ + + ]: 10343119 : handler->sequential_number < max_sequential_handler_number)
3885 : : {
3886 : 10343118 : SIGNAL_UNLOCK ();
3887 : 10342601 : return_accu = maybe_init_accumulator_unlocked (node, emission_return, &accu);
3888 : 10342601 : g_closure_invoke (handler->closure,
3889 : : return_accu,
3890 : : n_params,
3891 : : instance_and_params,
3892 : : &emission.ihint);
3893 [ + + ]: 10342689 : if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) &&
3894 [ + - ]: 322 : emission.state == EMISSION_RUN)
3895 : 322 : emission.state = EMISSION_STOP;
3896 : 10342491 : SIGNAL_LOCK ();
3897 : 10343112 : return_value_altered = TRUE;
3898 : :
3899 [ + + ]: 10343112 : tmp = emission.state == EMISSION_RUN ? handler->next : NULL;
3900 : : }
3901 : : else
3902 : 127457 : tmp = handler->next;
3903 : :
3904 [ + + ]: 10470569 : if (tmp)
3905 : 128642 : handler_ref (tmp);
3906 : 10470569 : handler_unref_R (signal_id, instance, handler_list);
3907 : 10470569 : handler_list = handler;
3908 : 10470569 : handler = tmp;
3909 : : }
3910 [ + + ]: 10470569 : while (handler);
3911 : :
3912 [ + + ]: 10341951 : if (emission.state == EMISSION_STOP)
3913 : 324 : goto EMIT_CLEANUP;
3914 [ + + ]: 10341627 : else if (emission.state == EMISSION_RESTART)
3915 : 21742 : goto EMIT_RESTART;
3916 : : }
3917 : :
3918 : 16806325 : emission.ihint.run_type &= ~G_SIGNAL_RUN_FIRST;
3919 : 16806325 : emission.ihint.run_type |= G_SIGNAL_RUN_LAST;
3920 : :
3921 [ + + + + ]: 16806325 : if ((node->flags & G_SIGNAL_RUN_LAST) && class_closure)
3922 : : {
3923 : 11838687 : emission.state = EMISSION_RUN;
3924 : :
3925 : 11838687 : emission.chain_type = G_TYPE_FROM_INSTANCE (instance);
3926 : 11838687 : SIGNAL_UNLOCK ();
3927 : 11832896 : return_accu = maybe_init_accumulator_unlocked (node, emission_return, &accu);
3928 : 11832896 : g_closure_invoke (class_closure,
3929 : : return_accu,
3930 : : n_params,
3931 : : instance_and_params,
3932 : : &emission.ihint);
3933 [ + + ]: 11833996 : if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) &&
3934 [ + - ]: 2 : emission.state == EMISSION_RUN)
3935 : 2 : emission.state = EMISSION_STOP;
3936 : 11832584 : SIGNAL_LOCK ();
3937 : 11838687 : emission.chain_type = G_TYPE_NONE;
3938 : 11838687 : return_value_altered = TRUE;
3939 : :
3940 [ + + ]: 11838687 : if (emission.state == EMISSION_STOP)
3941 : 2 : goto EMIT_CLEANUP;
3942 [ - + ]: 11838685 : else if (emission.state == EMISSION_RESTART)
3943 : 0 : goto EMIT_RESTART;
3944 : : }
3945 : :
3946 [ + + ]: 16806323 : if (handler_list)
3947 : : {
3948 : 10319884 : Handler *handler = handler_list;
3949 : :
3950 : 10319884 : emission.state = EMISSION_RUN;
3951 : 10319884 : handler_ref (handler);
3952 : : do
3953 : : {
3954 : : Handler *tmp;
3955 : :
3956 [ + + + - : 10319884 : if (handler->after && !handler->block_count && (!handler->detail || handler->detail == detail) &&
- + - - ]
3957 [ + - ]: 23 : handler->sequential_number < max_sequential_handler_number)
3958 : : {
3959 : 23 : SIGNAL_UNLOCK ();
3960 : 23 : return_accu = maybe_init_accumulator_unlocked (node, emission_return, &accu);
3961 : 23 : g_closure_invoke (handler->closure,
3962 : : return_accu,
3963 : : n_params,
3964 : : instance_and_params,
3965 : : &emission.ihint);
3966 [ + + ]: 23 : if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) &&
3967 [ + - ]: 2 : emission.state == EMISSION_RUN)
3968 : 2 : emission.state = EMISSION_STOP;
3969 : 23 : SIGNAL_LOCK ();
3970 : 23 : return_value_altered = TRUE;
3971 : :
3972 [ + + ]: 23 : tmp = emission.state == EMISSION_RUN ? handler->next : NULL;
3973 : : }
3974 : : else
3975 : 10319861 : tmp = handler->next;
3976 : :
3977 [ - + ]: 10319884 : if (tmp)
3978 : 0 : handler_ref (tmp);
3979 : 10319884 : handler_unref_R (signal_id, instance, handler);
3980 : 10319884 : handler = tmp;
3981 : : }
3982 [ - + ]: 10319884 : while (handler);
3983 : :
3984 [ + + ]: 10319884 : if (emission.state == EMISSION_STOP)
3985 : 2 : goto EMIT_CLEANUP;
3986 [ + - ]: 10319882 : else if (emission.state == EMISSION_RESTART)
3987 : 0 : goto EMIT_RESTART;
3988 : : }
3989 : :
3990 : 16806321 : EMIT_CLEANUP:
3991 : :
3992 : 16806649 : emission.ihint.run_type &= ~G_SIGNAL_RUN_LAST;
3993 : 16806649 : emission.ihint.run_type |= G_SIGNAL_RUN_CLEANUP;
3994 : :
3995 [ + + + - ]: 16806649 : if ((node->flags & G_SIGNAL_RUN_CLEANUP) && class_closure)
3996 : : {
3997 : 4 : gboolean need_unset = FALSE;
3998 : :
3999 : 4 : emission.state = EMISSION_STOP;
4000 : :
4001 : 4 : emission.chain_type = G_TYPE_FROM_INSTANCE (instance);
4002 : 4 : SIGNAL_UNLOCK ();
4003 [ + - - + ]: 4 : if (node->return_type != G_TYPE_NONE && !accumulator)
4004 : : {
4005 : 0 : g_value_init (&accu, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
4006 : 0 : need_unset = TRUE;
4007 : : }
4008 : 4 : g_closure_invoke (class_closure,
4009 [ + - ]: 4 : node->return_type != G_TYPE_NONE ? &accu : NULL,
4010 : : n_params,
4011 : : instance_and_params,
4012 : : &emission.ihint);
4013 [ - + ]: 4 : if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) &&
4014 [ # # ]: 0 : emission.state == EMISSION_RUN)
4015 : 0 : emission.state = EMISSION_STOP;
4016 [ - + ]: 4 : if (need_unset)
4017 : 0 : g_value_unset (&accu);
4018 : 4 : SIGNAL_LOCK ();
4019 : 4 : return_value_altered = TRUE;
4020 : :
4021 : 4 : emission.chain_type = G_TYPE_NONE;
4022 : :
4023 [ - + ]: 4 : if (emission.state == EMISSION_RESTART)
4024 : 0 : goto EMIT_RESTART;
4025 : : }
4026 : :
4027 [ + + ]: 16806649 : if (handler_list)
4028 : 10320209 : handler_unref_R (signal_id, instance, handler_list);
4029 : :
4030 : 16806649 : emission_pop (&emission);
4031 [ + + ]: 16806649 : if (accumulator)
4032 : 877 : g_value_unset (&accu);
4033 : :
4034 : 16806649 : TRACE(GOBJECT_SIGNAL_EMIT_END(node->signal_id, detail, instance, G_TYPE_FROM_INSTANCE (instance)));
4035 : :
4036 : 16806649 : return return_value_altered;
4037 : : }
4038 : :
4039 : : static void
4040 : 396 : add_invalid_closure_notify (Handler *handler,
4041 : : gpointer instance)
4042 : : {
4043 : 396 : g_closure_add_invalidate_notifier (handler->closure, instance, invalid_closure_notify);
4044 : 396 : handler->has_invalid_closure_notify = 1;
4045 : 396 : }
4046 : :
4047 : : static void
4048 : 539372 : remove_invalid_closure_notify (Handler *handler,
4049 : : gpointer instance)
4050 : : {
4051 [ + + ]: 539372 : if (handler->has_invalid_closure_notify)
4052 : : {
4053 : 339 : g_closure_remove_invalidate_notifier (handler->closure, instance, invalid_closure_notify);
4054 : 339 : handler->has_invalid_closure_notify = 0;
4055 : : }
4056 : 539372 : }
4057 : :
4058 : : static void
4059 : 57 : invalid_closure_notify (gpointer instance,
4060 : : GClosure *closure)
4061 : : {
4062 : : Handler *handler;
4063 : : guint signal_id;
4064 : :
4065 : 57 : SIGNAL_LOCK ();
4066 : :
4067 : 57 : handler = handler_lookup (instance, 0, closure, &signal_id);
4068 : : /* See https://bugzilla.gnome.org/show_bug.cgi?id=730296 for discussion about this... */
4069 : 57 : g_assert (handler != NULL);
4070 : 57 : g_assert (handler->closure == closure);
4071 : :
4072 : 57 : g_hash_table_remove (g_handlers, handler);
4073 : 57 : handler->sequential_number = 0;
4074 : 57 : handler->block_count = 1;
4075 : 57 : handler_unref_R (signal_id, instance, handler);
4076 : :
4077 : 57 : SIGNAL_UNLOCK ();
4078 : 57 : }
4079 : :
4080 : : static const gchar*
4081 : 2 : type_debug_name (GType type)
4082 : : {
4083 [ + - ]: 2 : if (type)
4084 : : {
4085 : 2 : const char *name = g_type_name (type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
4086 [ + - ]: 2 : return name ? name : "<unknown>";
4087 : : }
4088 : : else
4089 : 0 : return "<invalid>";
4090 : : }
4091 : :
4092 : : /**
4093 : : * g_signal_accumulator_true_handled:
4094 : : * @ihint: standard #GSignalAccumulator parameter
4095 : : * @return_accu: standard #GSignalAccumulator parameter
4096 : : * @handler_return: standard #GSignalAccumulator parameter
4097 : : * @dummy: standard #GSignalAccumulator parameter
4098 : : *
4099 : : * A predefined #GSignalAccumulator for signals that return a
4100 : : * boolean values. The behavior that this accumulator gives is
4101 : : * that a return of %TRUE stops the signal emission: no further
4102 : : * callbacks will be invoked, while a return of %FALSE allows
4103 : : * the emission to continue. The idea here is that a %TRUE return
4104 : : * indicates that the callback handled the signal, and no further
4105 : : * handling is needed.
4106 : : *
4107 : : * Since: 2.4
4108 : : *
4109 : : * Returns: standard #GSignalAccumulator result
4110 : : */
4111 : : gboolean
4112 : 853 : g_signal_accumulator_true_handled (GSignalInvocationHint *ihint,
4113 : : GValue *return_accu,
4114 : : const GValue *handler_return,
4115 : : gpointer dummy)
4116 : : {
4117 : : gboolean continue_emission;
4118 : : gboolean signal_handled;
4119 : :
4120 : 853 : signal_handled = g_value_get_boolean (handler_return);
4121 : 853 : g_value_set_boolean (return_accu, signal_handled);
4122 : 853 : continue_emission = !signal_handled;
4123 : :
4124 : 853 : return continue_emission;
4125 : : }
4126 : :
4127 : : /**
4128 : : * g_signal_accumulator_first_wins:
4129 : : * @ihint: standard #GSignalAccumulator parameter
4130 : : * @return_accu: standard #GSignalAccumulator parameter
4131 : : * @handler_return: standard #GSignalAccumulator parameter
4132 : : * @dummy: standard #GSignalAccumulator parameter
4133 : : *
4134 : : * A predefined #GSignalAccumulator for signals intended to be used as a
4135 : : * hook for application code to provide a particular value. Usually
4136 : : * only one such value is desired and multiple handlers for the same
4137 : : * signal don't make much sense (except for the case of the default
4138 : : * handler defined in the class structure, in which case you will
4139 : : * usually want the signal connection to override the class handler).
4140 : : *
4141 : : * This accumulator will use the return value from the first signal
4142 : : * handler that is run as the return value for the signal and not run
4143 : : * any further handlers (ie: the first handler "wins").
4144 : : *
4145 : : * Returns: standard #GSignalAccumulator result
4146 : : *
4147 : : * Since: 2.28
4148 : : **/
4149 : : gboolean
4150 : 9 : g_signal_accumulator_first_wins (GSignalInvocationHint *ihint,
4151 : : GValue *return_accu,
4152 : : const GValue *handler_return,
4153 : : gpointer dummy)
4154 : : {
4155 : 9 : g_value_copy (handler_return, return_accu);
4156 : 9 : return FALSE;
4157 : : }
4158 : :
4159 : : /**
4160 : : * g_clear_signal_handler:
4161 : : * @handler_id_ptr: A pointer to a handler ID (of type #gulong) of the handler to be disconnected.
4162 : : * @instance: (type GObject.Object): The instance to remove the signal handler from.
4163 : : * This pointer may be %NULL or invalid, if the handler ID is zero.
4164 : : *
4165 : : * Disconnects a handler from @instance so it will not be called during
4166 : : * any future or currently ongoing emissions of the signal it has been
4167 : : * connected to. The @handler_id_ptr is then set to zero, which is never a valid handler ID value (see g_signal_connect()).
4168 : : *
4169 : : * If the handler ID is 0 then this function does nothing.
4170 : : *
4171 : : * There is also a macro version of this function so that the code
4172 : : * will be inlined.
4173 : : *
4174 : : * Since: 2.62
4175 : : */
4176 : : void
4177 : 0 : (g_clear_signal_handler) (gulong *handler_id_ptr,
4178 : : gpointer instance)
4179 : : {
4180 : 0 : g_return_if_fail (handler_id_ptr != NULL);
4181 : :
4182 : : #ifndef g_clear_signal_handler
4183 : : #error g_clear_signal_handler() macro is not defined
4184 : : #endif
4185 : :
4186 : 0 : g_clear_signal_handler (handler_id_ptr, instance);
4187 : : }
|