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 <signal.h>
30 : : #include <stdint.h>
31 : : #include <string.h>
32 : :
33 : : #include "gsignal.h"
34 : : #include "gtype-private.h"
35 : : #include "gbsearcharray.h"
36 : : #include "gvaluecollector.h"
37 : : #include "gvaluetypes.h"
38 : : #include "gobject.h"
39 : : #include "genums.h"
40 : : #include "gobject_trace.h"
41 : :
42 : :
43 : : #define REPORT_BUG "please report occurrence circumstances to https://gitlab.gnome.org/GNOME/glib/issues/new"
44 : :
45 : : /* --- typedefs --- */
46 : : typedef struct _SignalNode SignalNode;
47 : : typedef struct _SignalKey SignalKey;
48 : : typedef struct _Emission Emission;
49 : : typedef struct _Handler Handler;
50 : : typedef struct _HandlerList HandlerList;
51 : : typedef struct _HandlerMatch HandlerMatch;
52 : : typedef enum
53 : : {
54 : : EMISSION_STOP,
55 : : EMISSION_RUN,
56 : : EMISSION_HOOK,
57 : : EMISSION_RESTART
58 : : } EmissionState;
59 : :
60 : :
61 : : /* --- prototypes --- */
62 : : static inline guint signal_id_lookup (const gchar *name,
63 : : GType itype);
64 : : static void signal_destroy_R (SignalNode *signal_node);
65 : : static inline HandlerList* handler_list_ensure (guint signal_id,
66 : : gpointer instance);
67 : : static inline HandlerList* handler_list_lookup (guint signal_id,
68 : : gpointer instance);
69 : : static inline Handler* handler_new (guint signal_id,
70 : : gpointer instance,
71 : : gboolean after);
72 : : static void handler_insert (guint signal_id,
73 : : gpointer instance,
74 : : Handler *handler);
75 : : static Handler* handler_lookup (gpointer instance,
76 : : gulong handler_id,
77 : : GClosure *closure,
78 : : guint *signal_id_p);
79 : : static inline HandlerMatch* handler_match_prepend (HandlerMatch *list,
80 : : Handler *handler,
81 : : guint signal_id);
82 : : static inline HandlerMatch* handler_match_free1_R (HandlerMatch *node,
83 : : gpointer instance);
84 : : static HandlerMatch* handlers_find (gpointer instance,
85 : : GSignalMatchType mask,
86 : : guint signal_id,
87 : : GQuark detail,
88 : : GClosure *closure,
89 : : gpointer func,
90 : : gpointer data,
91 : : gboolean one_and_only);
92 : : static inline void handler_ref (Handler *handler);
93 : : static inline void handler_unref_R (guint signal_id,
94 : : gpointer instance,
95 : : Handler *handler);
96 : : static gint handler_lists_cmp (gconstpointer node1,
97 : : gconstpointer node2);
98 : : static inline void emission_push (Emission *emission);
99 : : static inline void emission_pop (Emission *emission);
100 : : static inline Emission* emission_find (guint signal_id,
101 : : GQuark detail,
102 : : gpointer instance);
103 : : static gint class_closures_cmp (gconstpointer node1,
104 : : gconstpointer node2);
105 : : static gint signal_key_cmp (gconstpointer node1,
106 : : gconstpointer node2);
107 : : static gboolean signal_emit_unlocked_R (SignalNode *node,
108 : : GQuark detail,
109 : : gpointer instance,
110 : : GValue *return_value,
111 : : const GValue *instance_and_params);
112 : : static void add_invalid_closure_notify (Handler *handler,
113 : : gpointer instance);
114 : : static void remove_invalid_closure_notify (Handler *handler,
115 : : gpointer instance);
116 : : static void invalid_closure_notify (gpointer data,
117 : : GClosure *closure);
118 : : static const gchar * type_debug_name (GType type);
119 : : static void node_check_deprecated (const SignalNode *node);
120 : : static void node_update_single_va_closure (SignalNode *node);
121 : :
122 : :
123 : : /* --- structures --- */
124 : : typedef struct
125 : : {
126 : : GSignalAccumulator func;
127 : : gpointer data;
128 : : } SignalAccumulator;
129 : : typedef struct
130 : : {
131 : : GHook hook;
132 : : GQuark detail;
133 : : } SignalHook;
134 : : #define SIGNAL_HOOK(hook) ((SignalHook*) (hook))
135 : :
136 : : struct _SignalNode
137 : : {
138 : : /* permanent portion */
139 : : guint signal_id;
140 : : GType itype;
141 : : const gchar *name;
142 : : guint destroyed : 1;
143 : :
144 : : /* reinitializable portion */
145 : : guint flags : 9;
146 : : guint n_params : 8;
147 : : guint single_va_closure_is_valid : 1;
148 : : guint single_va_closure_is_after : 1;
149 : : GType *param_types; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */
150 : : GType return_type; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */
151 : : GBSearchArray *class_closure_bsa;
152 : : SignalAccumulator *accumulator;
153 : : GSignalCMarshaller c_marshaller;
154 : : GSignalCVaMarshaller va_marshaller;
155 : : GHookList *emission_hooks;
156 : :
157 : : GClosure *single_va_closure;
158 : : };
159 : :
160 : : #define SINGLE_VA_CLOSURE_EMPTY_MAGIC GINT_TO_POINTER(1) /* indicates single_va_closure is valid but empty */
161 : :
162 : : struct _SignalKey
163 : : {
164 : : GType itype;
165 : : GQuark quark;
166 : : guint signal_id;
167 : : };
168 : :
169 : : struct _Emission
170 : : {
171 : : Emission *next;
172 : : gpointer instance;
173 : : GSignalInvocationHint ihint;
174 : : EmissionState state;
175 : : GType chain_type;
176 : : };
177 : :
178 : : struct _HandlerList
179 : : {
180 : : guint signal_id;
181 : : Handler *handlers;
182 : : Handler *tail_before; /* normal signal handlers are appended here */
183 : : Handler *tail_after; /* CONNECT_AFTER handlers are appended here */
184 : : };
185 : :
186 : : struct _Handler
187 : : {
188 : : gulong sequential_number;
189 : : Handler *next;
190 : : Handler *prev;
191 : : GQuark detail;
192 : : guint signal_id;
193 : : guint ref_count;
194 : : guint block_count : 16;
195 : : #define HANDLER_MAX_BLOCK_COUNT (1 << 16)
196 : : guint after : 1;
197 : : guint has_invalid_closure_notify : 1;
198 : : GClosure *closure;
199 : : gpointer instance;
200 : : };
201 : : struct _HandlerMatch
202 : : {
203 : : Handler *handler;
204 : : HandlerMatch *next;
205 : : guint signal_id;
206 : : };
207 : :
208 : : typedef struct
209 : : {
210 : : GType instance_type; /* 0 for default closure */
211 : : GClosure *closure;
212 : : } ClassClosure;
213 : :
214 : :
215 : : /* --- variables --- */
216 : : static GBSearchArray *g_signal_key_bsa = NULL;
217 : : static const GBSearchConfig g_signal_key_bconfig = {
218 : : sizeof (SignalKey),
219 : : signal_key_cmp,
220 : : G_BSEARCH_ARRAY_ALIGN_POWER2,
221 : : };
222 : : static GBSearchConfig g_signal_hlbsa_bconfig = {
223 : : sizeof (HandlerList),
224 : : handler_lists_cmp,
225 : : 0,
226 : : };
227 : : static GBSearchConfig g_class_closure_bconfig = {
228 : : sizeof (ClassClosure),
229 : : class_closures_cmp,
230 : : 0,
231 : : };
232 : : static GHashTable *g_handler_list_bsa_ht = NULL;
233 : : static Emission *g_emissions = NULL;
234 : : static gulong g_handler_sequential_number = 1;
235 : : static GHashTable *g_handlers = NULL;
236 : :
237 : : G_LOCK_DEFINE_STATIC (g_signal_mutex);
238 : : #define SIGNAL_LOCK() G_LOCK (g_signal_mutex)
239 : : #define SIGNAL_UNLOCK() G_UNLOCK (g_signal_mutex)
240 : :
241 : :
242 : : /* --- signal nodes --- */
243 : : static guint g_n_signal_nodes = 0;
244 : : static SignalNode **g_signal_nodes = NULL;
245 : :
246 : : static inline SignalNode*
247 : 21267661 : LOOKUP_SIGNAL_NODE (guint signal_id)
248 : : {
249 : 21267661 : if (signal_id < g_n_signal_nodes)
250 : 21267661 : return g_signal_nodes[signal_id];
251 : : else
252 : 0 : return NULL;
253 : : }
254 : :
255 : :
256 : : /* --- functions --- */
257 : : /* @key must have already been validated with is_valid()
258 : : * Modifies @key in place. */
259 : : static void
260 : 4 : canonicalize_key (gchar *key)
261 : : {
262 : : gchar *p;
263 : :
264 : 49 : for (p = key; *p != 0; p++)
265 : : {
266 : 45 : gchar c = *p;
267 : :
268 : 45 : if (c == '_')
269 : 4 : *p = '-';
270 : : }
271 : 4 : }
272 : :
273 : : /* @key must have already been validated with is_valid() */
274 : : static gboolean
275 : 3980 : is_canonical (const gchar *key)
276 : : {
277 : 3980 : return (strchr (key, '_') == NULL);
278 : : }
279 : :
280 : : /**
281 : : * g_signal_is_valid_name:
282 : : * @name: the canonical name of the signal
283 : : *
284 : : * Validate a signal name. This can be useful for dynamically-generated signals
285 : : * which need to be validated at run-time before actually trying to create them.
286 : : *
287 : : * See [func@GObject.signal_new] for details of the rules for valid names.
288 : : * The rules for signal names are the same as those for property names.
289 : : *
290 : : * Returns: %TRUE if @name is a valid signal name, %FALSE otherwise.
291 : : * Since: 2.66
292 : : */
293 : : gboolean
294 : 1995 : 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 : 1995 : if (g_str_equal (name, "-gtk-private-changed"))
299 : 0 : return TRUE;
300 : :
301 : 1995 : return g_param_spec_is_valid_name (name);
302 : : }
303 : :
304 : : static inline guint
305 : 526804 : signal_id_lookup (const gchar *name,
306 : : GType itype)
307 : : {
308 : : GQuark quark;
309 : 526804 : GType *ifaces, type = itype;
310 : : SignalKey key;
311 : : guint n_ifaces;
312 : :
313 : 526804 : quark = g_quark_try_string (name);
314 : 526804 : key.quark = quark;
315 : :
316 : : /* try looking up signals for this type and its ancestors */
317 : : do
318 : : {
319 : : SignalKey *signal_key;
320 : :
321 : 935248 : key.itype = type;
322 : 935248 : signal_key = g_bsearch_array_lookup (g_signal_key_bsa, &g_signal_key_bconfig, &key);
323 : :
324 : 935248 : if (signal_key)
325 : 124101 : return signal_key->signal_id;
326 : :
327 : 811147 : type = g_type_parent (type);
328 : : }
329 : 811147 : while (type);
330 : :
331 : : /* no luck, try interfaces it exports */
332 : 402703 : ifaces = g_type_interfaces (itype, &n_ifaces);
333 : 804926 : while (n_ifaces--)
334 : : {
335 : : SignalKey *signal_key;
336 : :
337 : 802932 : key.itype = ifaces[n_ifaces];
338 : 802932 : signal_key = g_bsearch_array_lookup (g_signal_key_bsa, &g_signal_key_bconfig, &key);
339 : :
340 : 802932 : if (signal_key)
341 : : {
342 : 400709 : g_free (ifaces);
343 : 400709 : return signal_key->signal_id;
344 : : }
345 : : }
346 : 1994 : 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 : 1994 : 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 : 1991 : 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 : 24354555 : handler_lists_cmp (gconstpointer node1,
377 : : gconstpointer node2)
378 : : {
379 : 24354555 : const HandlerList *hlist1 = node1, *hlist2 = node2;
380 : :
381 : 24354555 : return G_BSEARCH_ARRAY_CMP (hlist1->signal_id, hlist2->signal_id);
382 : : }
383 : :
384 : : static inline HandlerList*
385 : 532257 : handler_list_ensure (guint signal_id,
386 : : gpointer instance)
387 : : {
388 : 532257 : GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
389 : : HandlerList key;
390 : :
391 : 532257 : key.signal_id = signal_id;
392 : 532257 : key.handlers = NULL;
393 : 532257 : key.tail_before = NULL;
394 : 532257 : key.tail_after = NULL;
395 : 532257 : if (!hlbsa)
396 : : {
397 : 108502 : hlbsa = g_bsearch_array_create (&g_signal_hlbsa_bconfig);
398 : : }
399 : 532257 : hlbsa = g_bsearch_array_insert (hlbsa, &g_signal_hlbsa_bconfig, &key);
400 : 532257 : g_hash_table_insert (g_handler_list_bsa_ht, instance, hlbsa);
401 : 532257 : return g_bsearch_array_lookup (hlbsa, &g_signal_hlbsa_bconfig, &key);
402 : : }
403 : :
404 : : static inline HandlerList*
405 : 16697883 : handler_list_lookup (guint signal_id,
406 : : gpointer instance)
407 : : {
408 : 16697883 : GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
409 : : HandlerList key;
410 : :
411 : 16697883 : key.signal_id = signal_id;
412 : :
413 : 16697883 : return hlbsa ? g_bsearch_array_lookup (hlbsa, &g_signal_hlbsa_bconfig, &key) : NULL;
414 : : }
415 : :
416 : : static guint
417 : 1595478 : handler_hash (gconstpointer key)
418 : : {
419 : 1595478 : return (guint)((Handler*)key)->sequential_number;
420 : : }
421 : :
422 : : static gboolean
423 : 1063313 : handler_equal (gconstpointer a, gconstpointer b)
424 : : {
425 : 1063313 : Handler *ha = (Handler *)a;
426 : 1063313 : Handler *hb = (Handler *)b;
427 : 2126510 : return (ha->sequential_number == hb->sequential_number) &&
428 : 1063197 : (ha->instance == hb->instance);
429 : : }
430 : :
431 : : static Handler*
432 : 531417 : handler_lookup (gpointer instance,
433 : : gulong handler_id,
434 : : GClosure *closure,
435 : : guint *signal_id_p)
436 : : {
437 : : GBSearchArray *hlbsa;
438 : :
439 : 531417 : if (handler_id)
440 : : {
441 : : Handler key;
442 : 531359 : key.sequential_number = handler_id;
443 : 531359 : key.instance = instance;
444 : 531359 : 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 : 402196 : handler_match_prepend (HandlerMatch *list,
475 : : Handler *handler,
476 : : guint signal_id)
477 : : {
478 : : HandlerMatch *node;
479 : :
480 : 402196 : node = g_slice_new (HandlerMatch);
481 : 402196 : node->handler = handler;
482 : 402196 : node->next = list;
483 : 402196 : node->signal_id = signal_id;
484 : 402196 : handler_ref (handler);
485 : :
486 : 402196 : return node;
487 : : }
488 : : static inline HandlerMatch*
489 : 402196 : handler_match_free1_R (HandlerMatch *node,
490 : : gpointer instance)
491 : : {
492 : 402196 : HandlerMatch *next = node->next;
493 : :
494 : 402196 : handler_unref_R (node->signal_id, instance, node->handler);
495 : 402196 : g_slice_free (HandlerMatch, node);
496 : :
497 : 402196 : return next;
498 : : }
499 : :
500 : : static HandlerMatch*
501 : 402365 : 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 : 402365 : HandlerMatch *mlist = NULL;
511 : :
512 : 402365 : if (mask & G_SIGNAL_MATCH_ID)
513 : : {
514 : 158 : HandlerList *hlist = handler_list_lookup (signal_id, instance);
515 : : Handler *handler;
516 : 158 : SignalNode *node = NULL;
517 : :
518 : 158 : 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 : 158 : mask = ~mask;
526 : 162 : for (handler = hlist ? hlist->handlers : NULL; handler; handler = handler->next)
527 : 86 : if (handler->sequential_number &&
528 : 86 : ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
529 : 86 : ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
530 : 86 : ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
531 : 86 : ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
532 : 86 : ((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 : 86 : mlist = handler_match_prepend (mlist, handler, signal_id);
537 : 86 : if (one_and_only)
538 : 82 : return mlist;
539 : : }
540 : : }
541 : : else
542 : : {
543 : 402207 : GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
544 : :
545 : 402207 : mask = ~mask;
546 : 402207 : if (hlbsa)
547 : : {
548 : : guint i;
549 : :
550 : 2005134 : for (i = 0; i < hlbsa->n_nodes; i++)
551 : : {
552 : 1602945 : HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, &g_signal_hlbsa_bconfig, i);
553 : 1602945 : SignalNode *node = NULL;
554 : : Handler *handler;
555 : :
556 : 1602945 : if (!(mask & G_SIGNAL_MATCH_FUNC))
557 : : {
558 : 1602937 : node = LOOKUP_SIGNAL_NODE (hlist->signal_id);
559 : 1602937 : if (!node->c_marshaller)
560 : 0 : continue;
561 : : }
562 : :
563 : 3130216 : for (handler = hlist->handlers; handler; handler = handler->next)
564 : 1527271 : if (handler->sequential_number &&
565 : 1527271 : ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
566 : 1527271 : ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
567 : 1527271 : ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
568 : 1002412 : ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
569 : 1002412 : ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
570 : 1002404 : G_REAL_CLOSURE (handler->closure)->meta_marshal == NULL &&
571 : 1002404 : ((GCClosure*) handler->closure)->callback == func)))
572 : : {
573 : 402110 : mlist = handler_match_prepend (mlist, handler, hlist->signal_id);
574 : 402110 : if (one_and_only)
575 : 0 : return mlist;
576 : : }
577 : : }
578 : : }
579 : : }
580 : :
581 : 402283 : return mlist;
582 : : }
583 : :
584 : : static inline Handler*
585 : 532257 : handler_new (guint signal_id, gpointer instance, gboolean after)
586 : : {
587 : 532257 : Handler *handler = g_slice_new (Handler);
588 : : #ifndef G_DISABLE_CHECKS
589 : 532257 : if (g_handler_sequential_number < 1)
590 : 0 : g_error (G_STRLOC ": handler id overflow, %s", REPORT_BUG);
591 : : #endif
592 : :
593 : 532257 : handler->sequential_number = g_handler_sequential_number++;
594 : 532257 : handler->prev = NULL;
595 : 532257 : handler->next = NULL;
596 : 532257 : handler->detail = 0;
597 : 532257 : handler->signal_id = signal_id;
598 : 532257 : handler->instance = instance;
599 : 532257 : handler->ref_count = 1;
600 : 532257 : handler->block_count = 0;
601 : 532257 : handler->after = after != FALSE;
602 : 532257 : handler->closure = NULL;
603 : 532257 : handler->has_invalid_closure_notify = 0;
604 : :
605 : 532257 : g_hash_table_add (g_handlers, handler);
606 : :
607 : 532257 : return handler;
608 : : }
609 : :
610 : : static inline void
611 : 20604098 : handler_ref (Handler *handler)
612 : : {
613 : 20604098 : g_return_if_fail (handler->ref_count > 0);
614 : :
615 : 20604098 : handler->ref_count++;
616 : : }
617 : :
618 : : static inline void
619 : 21135946 : handler_unref_R (guint signal_id,
620 : : gpointer instance,
621 : : Handler *handler)
622 : : {
623 : 21135946 : g_return_if_fail (handler->ref_count > 0);
624 : :
625 : 21135946 : handler->ref_count--;
626 : :
627 : 21135946 : if (G_UNLIKELY (handler->ref_count == 0))
628 : : {
629 : 531856 : HandlerList *hlist = NULL;
630 : :
631 : 531856 : if (handler->next)
632 : 1520 : handler->next->prev = handler->prev;
633 : 531856 : if (handler->prev) /* watch out for g_signal_handlers_destroy()! */
634 : 12255 : handler->prev->next = handler->next;
635 : : else
636 : : {
637 : 519601 : hlist = handler_list_lookup (signal_id, instance);
638 : 519601 : g_assert (hlist != NULL);
639 : 519601 : hlist->handlers = handler->next;
640 : : }
641 : :
642 : 531856 : if (instance)
643 : : {
644 : : /* check if we are removing the handler pointed to by tail_before */
645 : 531014 : if (!handler->after && (!handler->next || handler->next->after))
646 : : {
647 : 529493 : if (!hlist)
648 : 10392 : hlist = handler_list_lookup (signal_id, instance);
649 : 529493 : if (hlist)
650 : : {
651 : 529493 : g_assert (hlist->tail_before == handler); /* paranoid */
652 : 529493 : hlist->tail_before = handler->prev;
653 : : }
654 : : }
655 : :
656 : : /* check if we are removing the handler pointed to by tail_after */
657 : 531014 : if (!handler->next)
658 : : {
659 : 529494 : if (!hlist)
660 : 2 : hlist = handler_list_lookup (signal_id, instance);
661 : 529494 : if (hlist)
662 : : {
663 : 529494 : g_assert (hlist->tail_after == handler); /* paranoid */
664 : 529494 : hlist->tail_after = handler->prev;
665 : : }
666 : : }
667 : : }
668 : :
669 : 531856 : SIGNAL_UNLOCK ();
670 : 531856 : g_closure_unref (handler->closure);
671 : 531856 : SIGNAL_LOCK ();
672 : 531856 : g_slice_free (Handler, handler);
673 : : }
674 : : }
675 : :
676 : : static void
677 : 532257 : handler_insert (guint signal_id,
678 : : gpointer instance,
679 : : Handler *handler)
680 : : {
681 : : HandlerList *hlist;
682 : :
683 : 532257 : g_assert (handler->prev == NULL && handler->next == NULL); /* paranoid */
684 : :
685 : 532257 : hlist = handler_list_ensure (signal_id, instance);
686 : 532257 : if (!hlist->handlers)
687 : : {
688 : 520284 : hlist->handlers = handler;
689 : 520284 : if (!handler->after)
690 : 520283 : hlist->tail_before = handler;
691 : : }
692 : 11973 : else if (handler->after)
693 : : {
694 : 17 : handler->prev = hlist->tail_after;
695 : 17 : hlist->tail_after->next = handler;
696 : : }
697 : : else
698 : : {
699 : 11956 : if (hlist->tail_before)
700 : : {
701 : 11954 : handler->next = hlist->tail_before->next;
702 : 11954 : if (handler->next)
703 : 28 : handler->next->prev = handler;
704 : 11954 : handler->prev = hlist->tail_before;
705 : 11954 : 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 : 11956 : hlist->tail_before = handler;
715 : : }
716 : :
717 : 532257 : if (!handler->next)
718 : 532227 : hlist->tail_after = handler;
719 : 532257 : }
720 : :
721 : : static void
722 : 510 : node_update_single_va_closure (SignalNode *node)
723 : : {
724 : 510 : GClosure *closure = NULL;
725 : 510 : gboolean is_after = FALSE;
726 : :
727 : : /* Fast path single-handler without boxing the arguments in GValues */
728 : 510 : if (G_TYPE_IS_OBJECT (node->itype) &&
729 : 426 : (node->flags & (G_SIGNAL_MUST_COLLECT)) == 0 &&
730 : 403 : (node->emission_hooks == NULL || node->emission_hooks->hooks == NULL))
731 : : {
732 : : GSignalFlags run_type;
733 : : ClassClosure * cc;
734 : 395 : GBSearchArray *bsa = node->class_closure_bsa;
735 : :
736 : 395 : if (bsa == NULL || bsa->n_nodes == 0)
737 : 26 : closure = SINGLE_VA_CLOSURE_EMPTY_MAGIC;
738 : 369 : 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 : 365 : cc = g_bsearch_array_get_nth (bsa, &g_class_closure_bconfig, 0);
743 : 365 : if (cc->instance_type == 0)
744 : : {
745 : 365 : 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 : 365 : if (run_type == G_SIGNAL_RUN_FIRST ||
748 : : run_type == G_SIGNAL_RUN_LAST)
749 : : {
750 : 360 : closure = cc->closure;
751 : 360 : is_after = (run_type == G_SIGNAL_RUN_LAST);
752 : : }
753 : : }
754 : : }
755 : : }
756 : :
757 : 510 : node->single_va_closure_is_valid = TRUE;
758 : 510 : node->single_va_closure = closure;
759 : 510 : node->single_va_closure_is_after = (guint) is_after;
760 : 510 : }
761 : :
762 : : static inline void
763 : 9357220 : emission_push (Emission *emission)
764 : : {
765 : 9357220 : emission->next = g_emissions;
766 : 9357220 : g_emissions = emission;
767 : 9357220 : }
768 : :
769 : : static inline void
770 : 9357212 : emission_pop (Emission *emission)
771 : : {
772 : 9357212 : Emission *node, *last = NULL;
773 : :
774 : 9881049 : for (node = g_emissions; node; last = node, node = last->next)
775 : 9881049 : if (node == emission)
776 : : {
777 : 9357212 : if (last)
778 : 289829 : last->next = node->next;
779 : : else
780 : 9067383 : g_emissions = node->next;
781 : 9357212 : return;
782 : : }
783 : : g_assert_not_reached ();
784 : : }
785 : :
786 : : static inline Emission*
787 : 2660626 : emission_find (guint signal_id,
788 : : GQuark detail,
789 : : gpointer instance)
790 : : {
791 : : Emission *emission;
792 : :
793 : 3329696 : for (emission = g_emissions; emission; emission = emission->next)
794 : 805337 : if (emission->instance == instance &&
795 : 136334 : emission->ihint.signal_id == signal_id &&
796 : 136273 : emission->ihint.detail == detail)
797 : 136267 : return emission;
798 : 2524359 : 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 : 7805399 : signal_key_cmp (gconstpointer node1,
815 : : gconstpointer node2)
816 : : {
817 : 7805399 : const SignalKey *key1 = node1, *key2 = node2;
818 : :
819 : 7805399 : if (key1->itype == key2->itype)
820 : 1331416 : return G_BSEARCH_ARRAY_CMP (key1->quark, key2->quark);
821 : : else
822 : 6473983 : return G_BSEARCH_ARRAY_CMP (key1->itype, key2->itype);
823 : : }
824 : :
825 : : void
826 : 580 : _g_signal_init (void)
827 : : {
828 : 580 : SIGNAL_LOCK ();
829 : 580 : if (!g_n_signal_nodes)
830 : : {
831 : : /* setup handler list binary searchable array hash table (in german, that'd be one word ;) */
832 : 580 : g_handler_list_bsa_ht = g_hash_table_new (g_direct_hash, NULL);
833 : 580 : g_signal_key_bsa = g_bsearch_array_create (&g_signal_key_bconfig);
834 : :
835 : : /* invalid (0) signal_id */
836 : 580 : g_n_signal_nodes = 1;
837 : 580 : g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
838 : 580 : g_signal_nodes[0] = NULL;
839 : 580 : g_handlers = g_hash_table_new (handler_hash, handler_equal);
840 : : }
841 : 580 : SIGNAL_UNLOCK ();
842 : 580 : }
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 : 522498 : signal_parse_name (const gchar *name,
1044 : : GType itype,
1045 : : GQuark *detail_p,
1046 : : gboolean force_quark)
1047 : : {
1048 : 522498 : const gchar *colon = strchr (name, ':');
1049 : : guint signal_id;
1050 : :
1051 : 522498 : if (!colon)
1052 : : {
1053 : 522128 : signal_id = signal_id_lookup (name, itype);
1054 : 522128 : if (signal_id && detail_p)
1055 : 522125 : *detail_p = 0;
1056 : : }
1057 : 370 : else if (colon[1] == ':')
1058 : : {
1059 : : gchar buffer[32];
1060 : 366 : size_t l = (size_t) (colon - name);
1061 : :
1062 : 366 : if (colon[2] == '\0')
1063 : 2 : return 0;
1064 : :
1065 : 364 : if (l < 32)
1066 : : {
1067 : 364 : memcpy (buffer, name, l);
1068 : 364 : buffer[l] = 0;
1069 : 364 : 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 : 364 : if (signal_id && detail_p)
1082 : 363 : *detail_p = (force_quark ? g_quark_from_string : g_quark_try_string) (colon + 2);
1083 : : }
1084 : : else
1085 : 4 : signal_id = 0;
1086 : 522496 : 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 : 2323 : g_signal_lookup (const gchar *name,
1215 : : GType itype)
1216 : : {
1217 : : guint signal_id;
1218 : 2323 : g_return_val_if_fail (name != NULL, 0);
1219 : 2323 : g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
1220 : :
1221 : 2323 : SIGNAL_LOCK ();
1222 : 2323 : signal_id = signal_id_lookup (name, itype);
1223 : 2323 : SIGNAL_UNLOCK ();
1224 : 2323 : 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 : 2323 : 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 : 161 : 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 : 161 : g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), NULL);
1259 : 161 : g_return_val_if_fail (n_ids != NULL, NULL);
1260 : :
1261 : 161 : SIGNAL_LOCK ();
1262 : 161 : keys = g_bsearch_array_get_nth (g_signal_key_bsa, &g_signal_key_bconfig, 0);
1263 : 161 : n_nodes = g_bsearch_array_get_n_nodes (g_signal_key_bsa);
1264 : 161 : result = g_array_new (FALSE, FALSE, sizeof (guint));
1265 : :
1266 : 6378 : for (i = 0; i < n_nodes; i++)
1267 : 6217 : if (keys[i].itype == itype)
1268 : : {
1269 : 111 : g_array_append_val (result, keys[i].signal_id);
1270 : : }
1271 : 161 : *n_ids = result->len;
1272 : 161 : SIGNAL_UNLOCK ();
1273 : 161 : 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 : 161 : 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 : 85 : g_signal_query (guint signal_id,
1329 : : GSignalQuery *query)
1330 : : {
1331 : : SignalNode *node;
1332 : :
1333 : 85 : g_return_if_fail (query != NULL);
1334 : :
1335 : 85 : SIGNAL_LOCK ();
1336 : 85 : node = LOOKUP_SIGNAL_NODE (signal_id);
1337 : 85 : if (!node || node->destroyed)
1338 : 0 : query->signal_id = 0;
1339 : : else
1340 : : {
1341 : 85 : query->signal_id = node->signal_id;
1342 : 85 : query->signal_name = node->name;
1343 : 85 : query->itype = node->itype;
1344 : 85 : query->signal_flags = node->flags;
1345 : 85 : query->return_type = node->return_type;
1346 : 85 : query->n_params = node->n_params;
1347 : 85 : query->param_types = node->param_types;
1348 : : }
1349 : 85 : 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 : 1984 : 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 : 1984 : g_return_val_if_fail (signal_name != NULL, 0);
1415 : :
1416 : 1984 : va_start (args, n_params);
1417 : :
1418 : 3909 : signal_id = g_signal_new_valist (signal_name, itype, signal_flags,
1419 : 1925 : 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 : 1984 : va_end (args);
1424 : :
1425 : 1984 : 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 : 8388660 : signal_find_class_closure (SignalNode *node,
1500 : : GType itype)
1501 : : {
1502 : 8388660 : GBSearchArray *bsa = node->class_closure_bsa;
1503 : : ClassClosure *cc;
1504 : :
1505 : 8388660 : if (bsa)
1506 : : {
1507 : : ClassClosure key;
1508 : :
1509 : : /* cc->instance_type is 0 for default closure */
1510 : :
1511 : 8369113 : if (g_bsearch_array_get_n_nodes (bsa) == 1)
1512 : : {
1513 : 8369078 : cc = g_bsearch_array_get_nth (bsa, &g_class_closure_bconfig, 0);
1514 : 8369078 : if (cc && cc->instance_type == 0) /* check for default closure */
1515 : 8369078 : 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 : 19547 : cc = NULL;
1528 : 19582 : return cc;
1529 : : }
1530 : :
1531 : : static inline GClosure*
1532 : 8388562 : signal_lookup_closure (SignalNode *node,
1533 : : GTypeInstance *instance)
1534 : : {
1535 : : ClassClosure *cc;
1536 : :
1537 : 8388562 : cc = signal_find_class_closure (node, G_TYPE_FROM_INSTANCE (instance));
1538 : 8388562 : return cc ? cc->closure : NULL;
1539 : : }
1540 : :
1541 : : static void
1542 : 1934 : signal_add_class_closure (SignalNode *node,
1543 : : GType itype,
1544 : : GClosure *closure)
1545 : : {
1546 : : ClassClosure key;
1547 : :
1548 : 1934 : node->single_va_closure_is_valid = FALSE;
1549 : :
1550 : 1934 : if (!node->class_closure_bsa)
1551 : 1927 : node->class_closure_bsa = g_bsearch_array_create (&g_class_closure_bconfig);
1552 : 1934 : key.instance_type = itype;
1553 : 1934 : key.closure = g_closure_ref (closure);
1554 : 1934 : node->class_closure_bsa = g_bsearch_array_insert (node->class_closure_bsa,
1555 : : &g_class_closure_bconfig,
1556 : : &key);
1557 : 1934 : g_closure_sink (closure);
1558 : 1934 : if (node->c_marshaller && closure && G_CLOSURE_NEEDS_MARSHAL (closure))
1559 : : {
1560 : 1934 : g_closure_set_marshal (closure, node->c_marshaller);
1561 : 1934 : if (node->va_marshaller)
1562 : 701 : _g_closure_set_va_marshal (closure, node->va_marshaller);
1563 : : }
1564 : 1934 : }
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 : 1986 : 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 : 1986 : 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 : 1986 : g_return_val_if_fail (signal_name != NULL, 0);
1617 : 1986 : g_return_val_if_fail (g_signal_is_valid_name (signal_name), 0);
1618 : 1986 : g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
1619 : 1986 : if (n_params)
1620 : 1748 : g_return_val_if_fail (param_types != NULL, 0);
1621 : 1986 : g_return_val_if_fail ((return_type & G_SIGNAL_TYPE_STATIC_SCOPE) == 0, 0);
1622 : 1986 : if (return_type == (G_TYPE_NONE & ~G_SIGNAL_TYPE_STATIC_SCOPE))
1623 : 1470 : g_return_val_if_fail (accumulator == NULL, 0);
1624 : 1986 : if (!accumulator)
1625 : 1482 : g_return_val_if_fail (accu_data == NULL, 0);
1626 : 1986 : g_return_val_if_fail ((signal_flags & G_SIGNAL_ACCUMULATOR_FIRST_RUN) == 0, 0);
1627 : :
1628 : 1986 : 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 : 1985 : name = signal_name;
1637 : : }
1638 : :
1639 : 1986 : SIGNAL_LOCK ();
1640 : :
1641 : 1986 : signal_id = signal_id_lookup (name, itype);
1642 : 1986 : node = LOOKUP_SIGNAL_NODE (signal_id);
1643 : 1986 : 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 : 1986 : 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 : 5407 : for (i = 0; i < n_params; i++)
1664 : 3421 : 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 : 1986 : 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 : 1986 : if (!node)
1683 : : {
1684 : : SignalKey key;
1685 : :
1686 : 1986 : signal_id = g_n_signal_nodes++;
1687 : 1986 : node = g_new (SignalNode, 1);
1688 : 1986 : node->signal_id = signal_id;
1689 : 1986 : g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
1690 : 1986 : g_signal_nodes[signal_id] = node;
1691 : 1986 : node->itype = itype;
1692 : 1986 : key.itype = itype;
1693 : 1986 : key.signal_id = signal_id;
1694 : 1986 : node->name = g_intern_string (name);
1695 : 1986 : key.quark = g_quark_from_string (name);
1696 : 1986 : g_signal_key_bsa = g_bsearch_array_insert (g_signal_key_bsa, &g_signal_key_bconfig, &key);
1697 : :
1698 : 1986 : TRACE (GOBJECT_SIGNAL_NEW (signal_id, name, (uintmax_t) itype));
1699 : : }
1700 : 1986 : node->destroyed = FALSE;
1701 : :
1702 : : /* setup reinitializable portion */
1703 : 1986 : node->single_va_closure_is_valid = FALSE;
1704 : 1986 : node->flags = signal_flags & G_SIGNAL_FLAGS_MASK;
1705 : 1986 : node->n_params = n_params;
1706 : 1986 : node->param_types = g_memdup2 (param_types, sizeof (GType) * n_params);
1707 : 1986 : node->return_type = return_type;
1708 : 1986 : node->class_closure_bsa = NULL;
1709 : 1986 : if (accumulator)
1710 : : {
1711 : 504 : node->accumulator = g_new (SignalAccumulator, 1);
1712 : 504 : node->accumulator->func = accumulator;
1713 : 504 : node->accumulator->data = accu_data;
1714 : : }
1715 : : else
1716 : 1482 : node->accumulator = NULL;
1717 : :
1718 : 1986 : builtin_c_marshaller = NULL;
1719 : 1986 : 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 : 1986 : if (n_params == 0 && return_type == G_TYPE_NONE)
1724 : : {
1725 : 211 : builtin_c_marshaller = g_cclosure_marshal_VOID__VOID;
1726 : 211 : builtin_va_marshaller = g_cclosure_marshal_VOID__VOIDv;
1727 : : }
1728 : 1775 : 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 : 542 : ADD_CHECK (BOOLEAN)
1739 : 519 : ADD_CHECK (CHAR)
1740 : 519 : ADD_CHECK (UCHAR)
1741 : 519 : ADD_CHECK (INT)
1742 : 509 : ADD_CHECK (UINT)
1743 : 509 : ADD_CHECK (LONG)
1744 : 509 : ADD_CHECK (ULONG)
1745 : 509 : ADD_CHECK (ENUM)
1746 : 502 : ADD_CHECK (FLAGS)
1747 : 502 : ADD_CHECK (FLOAT)
1748 : 502 : ADD_CHECK (DOUBLE)
1749 : 501 : ADD_CHECK (STRING)
1750 : 451 : 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 : 1986 : if (c_marshaller == NULL)
1758 : : {
1759 : 744 : if (builtin_c_marshaller)
1760 : : {
1761 : 723 : c_marshaller = builtin_c_marshaller;
1762 : 723 : 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 : 1242 : va_marshaller = NULL;
1772 : :
1773 : 1986 : node->c_marshaller = c_marshaller;
1774 : 1986 : node->va_marshaller = va_marshaller;
1775 : 1986 : node->emission_hooks = NULL;
1776 : 1986 : if (class_closure)
1777 : 1927 : signal_add_class_closure (node, 0, class_closure);
1778 : :
1779 : 1986 : SIGNAL_UNLOCK ();
1780 : :
1781 : 1986 : g_free (signal_name_copy);
1782 : :
1783 : 1986 : 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 : 1059 : g_signal_set_va_marshaller (guint signal_id,
1801 : : GType instance_type,
1802 : : GSignalCVaMarshaller va_marshaller)
1803 : : {
1804 : : SignalNode *node;
1805 : :
1806 : 1059 : g_return_if_fail (signal_id > 0);
1807 : 1059 : g_return_if_fail (va_marshaller != NULL);
1808 : :
1809 : 1059 : SIGNAL_LOCK ();
1810 : 1059 : node = LOOKUP_SIGNAL_NODE (signal_id);
1811 : 1059 : if (node)
1812 : : {
1813 : 1059 : node->va_marshaller = va_marshaller;
1814 : 1059 : if (node->class_closure_bsa)
1815 : : {
1816 : 1051 : ClassClosure *cc = g_bsearch_array_get_nth (node->class_closure_bsa, &g_class_closure_bconfig, 0);
1817 : 1051 : if (cc->closure->marshal == node->c_marshaller)
1818 : 1051 : _g_closure_set_va_marshal (cc->closure, va_marshaller);
1819 : : }
1820 : :
1821 : 1059 : node->single_va_closure_is_valid = FALSE;
1822 : : }
1823 : :
1824 : 1059 : 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 : 1985 : 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 : 1985 : GType *param_types_heap = NULL;
1872 : : GType *param_types;
1873 : : guint i;
1874 : : guint signal_id;
1875 : :
1876 : 1985 : param_types = param_types_stack;
1877 : 1985 : if (n_params > 0)
1878 : : {
1879 : 1748 : 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 : 5169 : for (i = 0; i < n_params; i++)
1886 : 3421 : param_types[i] = va_arg (args, GType);
1887 : : }
1888 : :
1889 : 1985 : 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 : 1985 : g_free (param_types_heap);
1893 : :
1894 : 1985 : 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 name doesn’t exist,
2305 : : * a critical warning is emitted. No validation is performed on the
2306 : : * ‘detail’ string when specified in @detailed_signal, other than a
2307 : : * non-empty check.
2308 : : *
2309 : : * Refer to the [signals documentation](signals.html) for more
2310 : : * details.
2311 : : *
2312 : : * Returns: the handler ID (always greater than 0)
2313 : : */
2314 : : gulong
2315 : 10252 : g_signal_connect_closure_by_id (gpointer instance,
2316 : : guint signal_id,
2317 : : GQuark detail,
2318 : : GClosure *closure,
2319 : : gboolean after)
2320 : : {
2321 : : SignalNode *node;
2322 : 10252 : gulong handler_seq_no = 0;
2323 : :
2324 : 10252 : g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
2325 : 10252 : g_return_val_if_fail (signal_id > 0, 0);
2326 : 10252 : g_return_val_if_fail (closure != NULL, 0);
2327 : :
2328 : 10252 : SIGNAL_LOCK ();
2329 : 10252 : node = LOOKUP_SIGNAL_NODE (signal_id);
2330 : 10252 : if (node)
2331 : : {
2332 : 10252 : if (detail && !(node->flags & G_SIGNAL_DETAILED))
2333 : 0 : g_critical ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
2334 : 10252 : else if (!g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
2335 : 0 : g_critical ("%s: signal id '%u' is invalid for instance '%p'", G_STRLOC, signal_id, instance);
2336 : : else
2337 : : {
2338 : 10252 : Handler *handler = handler_new (signal_id, instance, after);
2339 : :
2340 : 10252 : if (G_TYPE_IS_OBJECT (node->itype))
2341 : 10252 : _g_object_set_has_signal_handler ((GObject *) instance, signal_id);
2342 : :
2343 : 10252 : handler_seq_no = handler->sequential_number;
2344 : 10252 : handler->detail = detail;
2345 : 10252 : handler->closure = g_closure_ref (closure);
2346 : 10252 : g_closure_sink (closure);
2347 : 10252 : add_invalid_closure_notify (handler, instance);
2348 : 10252 : handler_insert (signal_id, instance, handler);
2349 : 10252 : if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (closure))
2350 : : {
2351 : 10236 : g_closure_set_marshal (closure, node->c_marshaller);
2352 : 10236 : if (node->va_marshaller)
2353 : 10236 : _g_closure_set_va_marshal (closure, node->va_marshaller);
2354 : : }
2355 : : }
2356 : : }
2357 : : else
2358 : 0 : g_critical ("%s: signal id '%u' is invalid for instance '%p'", G_STRLOC, signal_id, instance);
2359 : 10252 : SIGNAL_UNLOCK ();
2360 : :
2361 : 10252 : return handler_seq_no;
2362 : : }
2363 : :
2364 : : /**
2365 : : * g_signal_connect_closure:
2366 : : * @instance: (type GObject.Object): the instance to connect to.
2367 : : * @detailed_signal: a string of the form "signal-name::detail".
2368 : : * @closure: (not nullable): the closure to connect.
2369 : : * @after: whether the handler should be called before or after the
2370 : : * default handler of the signal.
2371 : : *
2372 : : * Connects a closure to a signal for a particular object.
2373 : : *
2374 : : * If @closure is a floating reference (see g_closure_sink()), this function
2375 : : * takes ownership of @closure.
2376 : : *
2377 : : * This function cannot fail. If the given signal name doesn’t exist,
2378 : : * a critical warning is emitted. No validation is performed on the
2379 : : * ‘detail’ string when specified in @detailed_signal, other than a
2380 : : * non-empty check.
2381 : : *
2382 : : * Refer to the [signals documentation](signals.html) for more
2383 : : * details.
2384 : : *
2385 : : * Returns: the handler ID (always greater than 0)
2386 : : */
2387 : : gulong
2388 : 83 : g_signal_connect_closure (gpointer instance,
2389 : : const gchar *detailed_signal,
2390 : : GClosure *closure,
2391 : : gboolean after)
2392 : : {
2393 : : guint signal_id;
2394 : 83 : gulong handler_seq_no = 0;
2395 : 83 : GQuark detail = 0;
2396 : : GType itype;
2397 : :
2398 : 83 : g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
2399 : 83 : g_return_val_if_fail (detailed_signal != NULL, 0);
2400 : 83 : g_return_val_if_fail (closure != NULL, 0);
2401 : :
2402 : 83 : SIGNAL_LOCK ();
2403 : 83 : itype = G_TYPE_FROM_INSTANCE (instance);
2404 : 83 : signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
2405 : 83 : if (signal_id)
2406 : : {
2407 : 83 : SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
2408 : :
2409 : 83 : if (detail && !(node->flags & G_SIGNAL_DETAILED))
2410 : 0 : g_critical ("%s: signal '%s' does not support details", G_STRLOC, detailed_signal);
2411 : 83 : else if (!g_type_is_a (itype, node->itype))
2412 : 0 : g_critical ("%s: signal '%s' is invalid for instance '%p' of type '%s'",
2413 : : G_STRLOC, detailed_signal, instance, g_type_name (itype));
2414 : : else
2415 : : {
2416 : 83 : Handler *handler = handler_new (signal_id, instance, after);
2417 : :
2418 : 83 : if (G_TYPE_IS_OBJECT (node->itype))
2419 : 60 : _g_object_set_has_signal_handler ((GObject *) instance, signal_id);
2420 : :
2421 : 83 : handler_seq_no = handler->sequential_number;
2422 : 83 : handler->detail = detail;
2423 : 83 : handler->closure = g_closure_ref (closure);
2424 : 83 : g_closure_sink (closure);
2425 : 83 : add_invalid_closure_notify (handler, instance);
2426 : 83 : handler_insert (signal_id, instance, handler);
2427 : 83 : if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure))
2428 : : {
2429 : 82 : g_closure_set_marshal (handler->closure, node->c_marshaller);
2430 : 82 : if (node->va_marshaller)
2431 : 59 : _g_closure_set_va_marshal (handler->closure, node->va_marshaller);
2432 : : }
2433 : : }
2434 : : }
2435 : : else
2436 : 0 : g_critical ("%s: signal '%s' is invalid for instance '%p' of type '%s'",
2437 : : G_STRLOC, detailed_signal, instance, g_type_name (itype));
2438 : 83 : SIGNAL_UNLOCK ();
2439 : :
2440 : 83 : return handler_seq_no;
2441 : : }
2442 : :
2443 : : static void
2444 : 521955 : node_check_deprecated (const SignalNode *node)
2445 : : {
2446 : : static const gchar * g_enable_diagnostic = NULL;
2447 : :
2448 : 521955 : if (G_UNLIKELY (!g_enable_diagnostic))
2449 : : {
2450 : 203 : g_enable_diagnostic = g_getenv ("G_ENABLE_DIAGNOSTIC");
2451 : 203 : if (!g_enable_diagnostic)
2452 : 0 : g_enable_diagnostic = "0";
2453 : : }
2454 : :
2455 : 521955 : if (g_enable_diagnostic[0] == '1')
2456 : : {
2457 : 521951 : if (node->flags & G_SIGNAL_DEPRECATED)
2458 : : {
2459 : 0 : g_warning ("The signal %s::%s is deprecated and shouldn't be used "
2460 : : "anymore. It will be removed in a future version.",
2461 : : type_debug_name (node->itype), node->name);
2462 : : }
2463 : : }
2464 : 521955 : }
2465 : :
2466 : : /**
2467 : : * g_signal_connect_data:
2468 : : * @instance: (type GObject.Object): the instance to connect to.
2469 : : * @detailed_signal: a string of the form "signal-name::detail".
2470 : : * @c_handler: (not nullable): the #GCallback to connect.
2471 : : * @data: (nullable) (closure c_handler): data to pass to @c_handler calls.
2472 : : * @destroy_data: (nullable) (destroy data): a #GClosureNotify for @data.
2473 : : * @connect_flags: a combination of #GConnectFlags.
2474 : : *
2475 : : * Connects a #GCallback function to a signal for a particular object. Similar
2476 : : * to g_signal_connect(), but allows to provide a #GClosureNotify for the data
2477 : : * which will be called when the signal handler is disconnected and no longer
2478 : : * used. Specify @connect_flags if you need `..._after()` or
2479 : : * `..._swapped()` variants of this function.
2480 : : *
2481 : : * This function cannot fail. If the given signal name doesn’t exist,
2482 : : * a critical warning is emitted. No validation is performed on the
2483 : : * ‘detail’ string when specified in @detailed_signal, other than a
2484 : : * non-empty check.
2485 : : *
2486 : : * Refer to the [signals documentation](signals.html) for more
2487 : : * details.
2488 : : *
2489 : : * Returns: the handler ID (always greater than 0)
2490 : : */
2491 : : gulong
2492 : 521922 : g_signal_connect_data (gpointer instance,
2493 : : const gchar *detailed_signal,
2494 : : GCallback c_handler,
2495 : : gpointer data,
2496 : : GClosureNotify destroy_data,
2497 : : GConnectFlags connect_flags)
2498 : : {
2499 : : guint signal_id;
2500 : 521922 : gulong handler_seq_no = 0;
2501 : 521922 : GQuark detail = 0;
2502 : : GType itype;
2503 : : gboolean swapped, after;
2504 : :
2505 : 521922 : g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
2506 : 521922 : g_return_val_if_fail (detailed_signal != NULL, 0);
2507 : 521922 : g_return_val_if_fail (c_handler != NULL, 0);
2508 : :
2509 : 521922 : swapped = (connect_flags & G_CONNECT_SWAPPED) != FALSE;
2510 : 521922 : after = (connect_flags & G_CONNECT_AFTER) != FALSE;
2511 : :
2512 : 521922 : SIGNAL_LOCK ();
2513 : 521922 : itype = G_TYPE_FROM_INSTANCE (instance);
2514 : 521922 : signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
2515 : 521922 : if (signal_id)
2516 : : {
2517 : 521922 : SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
2518 : :
2519 : 521922 : node_check_deprecated (node);
2520 : :
2521 : 521922 : if (detail && !(node->flags & G_SIGNAL_DETAILED))
2522 : 0 : g_critical ("%s: signal '%s' does not support details", G_STRLOC, detailed_signal);
2523 : 521922 : else if (!g_type_is_a (itype, node->itype))
2524 : 0 : g_critical ("%s: signal '%s' is invalid for instance '%p' of type '%s'",
2525 : : G_STRLOC, detailed_signal, instance, g_type_name (itype));
2526 : : else
2527 : : {
2528 : 521922 : Handler *handler = handler_new (signal_id, instance, after);
2529 : :
2530 : 521922 : if (G_TYPE_IS_OBJECT (node->itype))
2531 : 121371 : _g_object_set_has_signal_handler ((GObject *) instance, signal_id);
2532 : :
2533 : 521922 : handler_seq_no = handler->sequential_number;
2534 : 521922 : handler->detail = detail;
2535 : 521922 : handler->closure = g_closure_ref ((swapped ? g_cclosure_new_swap : g_cclosure_new) (c_handler, data, destroy_data));
2536 : 521922 : g_closure_sink (handler->closure);
2537 : 521922 : handler_insert (signal_id, instance, handler);
2538 : 521922 : if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure))
2539 : : {
2540 : 521922 : g_closure_set_marshal (handler->closure, node->c_marshaller);
2541 : 521922 : if (node->va_marshaller)
2542 : 521810 : _g_closure_set_va_marshal (handler->closure, node->va_marshaller);
2543 : : }
2544 : : }
2545 : : }
2546 : : else
2547 : 0 : g_critical ("%s: signal '%s' is invalid for instance '%p' of type '%s'",
2548 : : G_STRLOC, detailed_signal, instance, g_type_name (itype));
2549 : 521922 : SIGNAL_UNLOCK ();
2550 : :
2551 : 521922 : return handler_seq_no;
2552 : : }
2553 : :
2554 : : static void
2555 : : signal_handler_block_unlocked (gpointer instance,
2556 : : gulong handler_id);
2557 : :
2558 : : /**
2559 : : * g_signal_handler_block:
2560 : : * @instance: (type GObject.Object): The instance to block the signal handler of.
2561 : : * @handler_id: Handler id of the handler to be blocked.
2562 : : *
2563 : : * Blocks a handler of an instance so it will not be called during any
2564 : : * signal emissions unless it is unblocked again. Thus "blocking" a
2565 : : * signal handler means to temporarily deactivate it, a signal handler
2566 : : * has to be unblocked exactly the same amount of times it has been
2567 : : * blocked before to become active again.
2568 : : *
2569 : : * The @handler_id has to be a valid signal handler id, connected to a
2570 : : * signal of @instance.
2571 : : */
2572 : : void
2573 : 186 : g_signal_handler_block (gpointer instance,
2574 : : gulong handler_id)
2575 : : {
2576 : 186 : g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
2577 : 186 : g_return_if_fail (handler_id > 0);
2578 : :
2579 : 186 : SIGNAL_LOCK ();
2580 : 186 : signal_handler_block_unlocked (instance, handler_id);
2581 : 186 : SIGNAL_UNLOCK ();
2582 : : }
2583 : :
2584 : : static void
2585 : 189 : signal_handler_block_unlocked (gpointer instance,
2586 : : gulong handler_id)
2587 : : {
2588 : : Handler *handler;
2589 : :
2590 : 189 : handler = handler_lookup (instance, handler_id, NULL, NULL);
2591 : 189 : if (handler)
2592 : : {
2593 : : #ifndef G_DISABLE_CHECKS
2594 : 189 : if (handler->block_count >= HANDLER_MAX_BLOCK_COUNT - 1)
2595 : 0 : g_error (G_STRLOC ": handler block_count overflow, %s", REPORT_BUG);
2596 : : #endif
2597 : 189 : handler->block_count += 1;
2598 : : }
2599 : : else
2600 : 0 : g_critical ("%s: instance '%p' has no handler with id '%lu'", G_STRLOC, instance, handler_id);
2601 : 189 : }
2602 : :
2603 : : static void
2604 : : signal_handler_unblock_unlocked (gpointer instance,
2605 : : gulong handler_id);
2606 : :
2607 : : /**
2608 : : * g_signal_handler_unblock:
2609 : : * @instance: (type GObject.Object): The instance to unblock the signal handler of.
2610 : : * @handler_id: Handler id of the handler to be unblocked.
2611 : : *
2612 : : * Undoes the effect of a previous g_signal_handler_block() call. A
2613 : : * blocked handler is skipped during signal emissions and will not be
2614 : : * invoked, unblocking it (for exactly the amount of times it has been
2615 : : * blocked before) reverts its "blocked" state, so the handler will be
2616 : : * recognized by the signal system and is called upon future or
2617 : : * currently ongoing signal emissions (since the order in which
2618 : : * handlers are called during signal emissions is deterministic,
2619 : : * whether the unblocked handler in question is called as part of a
2620 : : * currently ongoing emission depends on how far that emission has
2621 : : * proceeded yet).
2622 : : *
2623 : : * The @handler_id has to be a valid id of a signal handler that is
2624 : : * connected to a signal of @instance and is currently blocked.
2625 : : */
2626 : : void
2627 : 170 : g_signal_handler_unblock (gpointer instance,
2628 : : gulong handler_id)
2629 : : {
2630 : 170 : g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
2631 : 170 : g_return_if_fail (handler_id > 0);
2632 : :
2633 : 170 : SIGNAL_LOCK ();
2634 : 170 : signal_handler_unblock_unlocked (instance, handler_id);
2635 : 170 : SIGNAL_UNLOCK ();
2636 : : }
2637 : :
2638 : : static void
2639 : 173 : signal_handler_unblock_unlocked (gpointer instance,
2640 : : gulong handler_id)
2641 : : {
2642 : : Handler *handler;
2643 : :
2644 : 173 : handler = handler_lookup (instance, handler_id, NULL, NULL);
2645 : 173 : if (handler)
2646 : : {
2647 : 173 : if (handler->block_count)
2648 : 173 : handler->block_count -= 1;
2649 : : else
2650 : 0 : g_critical (G_STRLOC ": handler '%lu' of instance '%p' is not blocked", handler_id, instance);
2651 : : }
2652 : : else
2653 : 0 : g_critical ("%s: instance '%p' has no handler with id '%lu'", G_STRLOC, instance, handler_id);
2654 : 173 : }
2655 : :
2656 : : static void
2657 : : signal_handler_disconnect_unlocked (gpointer instance,
2658 : : gulong handler_id);
2659 : :
2660 : : /**
2661 : : * g_signal_handler_disconnect:
2662 : : * @instance: (type GObject.Object): The instance to remove the signal handler from.
2663 : : * @handler_id: Handler id of the handler to be disconnected.
2664 : : *
2665 : : * Disconnects a handler from an instance so it will not be called during
2666 : : * any future or currently ongoing emissions of the signal it has been
2667 : : * connected to. The @handler_id becomes invalid and may be reused.
2668 : : *
2669 : : * The @handler_id has to be a valid signal handler id, connected to a
2670 : : * signal of @instance.
2671 : : */
2672 : : void
2673 : 128860 : g_signal_handler_disconnect (gpointer instance,
2674 : : gulong handler_id)
2675 : : {
2676 : 128860 : g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
2677 : 128860 : g_return_if_fail (handler_id > 0);
2678 : :
2679 : 128860 : SIGNAL_LOCK ();
2680 : 128860 : signal_handler_disconnect_unlocked (instance, handler_id);
2681 : 128860 : SIGNAL_UNLOCK ();
2682 : : }
2683 : :
2684 : : static void
2685 : 530968 : signal_handler_disconnect_unlocked (gpointer instance,
2686 : : gulong handler_id)
2687 : : {
2688 : : Handler *handler;
2689 : :
2690 : 530968 : handler = handler_lookup (instance, handler_id, 0, 0);
2691 : 530968 : if (handler)
2692 : : {
2693 : 530963 : g_hash_table_remove (g_handlers, handler);
2694 : 530963 : handler->sequential_number = 0;
2695 : 530963 : handler->block_count = 1;
2696 : 530963 : remove_invalid_closure_notify (handler, instance);
2697 : 530963 : handler_unref_R (handler->signal_id, instance, handler);
2698 : : }
2699 : : else
2700 : 5 : g_critical ("%s: instance '%p' has no handler with id '%lu'", G_STRLOC, instance, handler_id);
2701 : 530968 : }
2702 : :
2703 : : /**
2704 : : * g_signal_handler_is_connected:
2705 : : * @instance: (type GObject.Object): The instance where a signal handler is sought.
2706 : : * @handler_id: the handler ID.
2707 : : *
2708 : : * Returns whether @handler_id is the ID of a handler connected to @instance.
2709 : : *
2710 : : * Returns: whether @handler_id identifies a handler connected to @instance.
2711 : : */
2712 : : gboolean
2713 : 30 : g_signal_handler_is_connected (gpointer instance,
2714 : : gulong handler_id)
2715 : : {
2716 : : Handler *handler;
2717 : : gboolean connected;
2718 : :
2719 : 30 : g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
2720 : :
2721 : 30 : SIGNAL_LOCK ();
2722 : 30 : handler = handler_lookup (instance, handler_id, NULL, NULL);
2723 : 30 : connected = handler != NULL;
2724 : 30 : SIGNAL_UNLOCK ();
2725 : :
2726 : 30 : return connected;
2727 : : }
2728 : :
2729 : : /**
2730 : : * g_signal_handlers_destroy:
2731 : : * @instance: (type GObject.Object): The instance whose signal handlers are destroyed
2732 : : *
2733 : : * Destroy all signal handlers of a type instance. This function is
2734 : : * an implementation detail of the #GObject dispose implementation,
2735 : : * and should not be used outside of the type system.
2736 : : */
2737 : : void
2738 : 15880734 : g_signal_handlers_destroy (gpointer instance)
2739 : : {
2740 : : GBSearchArray *hlbsa;
2741 : :
2742 : 15880734 : g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
2743 : :
2744 : 15880734 : SIGNAL_LOCK ();
2745 : 15880734 : hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
2746 : 15880734 : if (hlbsa)
2747 : : {
2748 : : guint i;
2749 : :
2750 : : /* reentrancy caution, delete instance trace first */
2751 : 107870 : g_hash_table_remove (g_handler_list_bsa_ht, instance);
2752 : :
2753 : 216237 : for (i = 0; i < hlbsa->n_nodes; i++)
2754 : : {
2755 : 108367 : HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, &g_signal_hlbsa_bconfig, i);
2756 : 108367 : Handler *handler = hlist->handlers;
2757 : :
2758 : 109209 : while (handler)
2759 : : {
2760 : 842 : Handler *tmp = handler;
2761 : :
2762 : 842 : handler = tmp->next;
2763 : 842 : tmp->block_count = 1;
2764 : : /* cruel unlink, this works because _all_ handlers vanish */
2765 : 842 : tmp->next = NULL;
2766 : 842 : tmp->prev = tmp;
2767 : 842 : if (tmp->sequential_number)
2768 : : {
2769 : 842 : g_hash_table_remove (g_handlers, tmp);
2770 : 842 : remove_invalid_closure_notify (tmp, instance);
2771 : 842 : tmp->sequential_number = 0;
2772 : 842 : handler_unref_R (0, NULL, tmp);
2773 : : }
2774 : : }
2775 : : }
2776 : 107870 : g_bsearch_array_free (hlbsa, &g_signal_hlbsa_bconfig);
2777 : : }
2778 : 15880734 : SIGNAL_UNLOCK ();
2779 : : }
2780 : :
2781 : : /**
2782 : : * g_signal_handler_find:
2783 : : * @instance: (type GObject.Object): The instance owning the signal handler to be found.
2784 : : * @mask: Mask indicating which of @signal_id, @detail, @closure, @func
2785 : : * and/or @data the handler has to match.
2786 : : * @signal_id: Signal the handler has to be connected to.
2787 : : * @detail: Signal detail the handler has to be connected to.
2788 : : * @closure: (nullable): The closure the handler will invoke.
2789 : : * @func: The C closure callback of the handler (useless for non-C closures).
2790 : : * @data: (nullable) (closure closure): The closure data of the handler's closure.
2791 : : *
2792 : : * Finds the first signal handler that matches certain selection criteria.
2793 : : * The criteria mask is passed as an OR-ed combination of #GSignalMatchType
2794 : : * flags, and the criteria values are passed as arguments.
2795 : : * The match @mask has to be non-0 for successful matches.
2796 : : * If no handler was found, 0 is returned.
2797 : : *
2798 : : * Returns: A valid non-0 signal handler id for a successful match.
2799 : : */
2800 : : gulong
2801 : 13 : g_signal_handler_find (gpointer instance,
2802 : : GSignalMatchType mask,
2803 : : guint signal_id,
2804 : : GQuark detail,
2805 : : GClosure *closure,
2806 : : gpointer func,
2807 : : gpointer data)
2808 : : {
2809 : 13 : gulong handler_seq_no = 0;
2810 : :
2811 : 13 : g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
2812 : 13 : g_return_val_if_fail ((mask & (unsigned) ~G_SIGNAL_MATCH_MASK) == 0, 0);
2813 : :
2814 : 13 : if (mask & G_SIGNAL_MATCH_MASK)
2815 : : {
2816 : : HandlerMatch *mlist;
2817 : :
2818 : 13 : SIGNAL_LOCK ();
2819 : 13 : mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, TRUE);
2820 : 13 : if (mlist)
2821 : : {
2822 : 2 : handler_seq_no = mlist->handler->sequential_number;
2823 : 2 : handler_match_free1_R (mlist, instance);
2824 : : }
2825 : 13 : SIGNAL_UNLOCK ();
2826 : : }
2827 : :
2828 : 13 : return handler_seq_no;
2829 : : }
2830 : :
2831 : : typedef void (*CallbackHandlerFunc) (gpointer instance, gulong handler_seq_no);
2832 : :
2833 : : static guint
2834 : 402205 : signal_handlers_foreach_matched_unlocked_R (gpointer instance,
2835 : : GSignalMatchType mask,
2836 : : guint signal_id,
2837 : : GQuark detail,
2838 : : GClosure *closure,
2839 : : gpointer func,
2840 : : gpointer data,
2841 : : CallbackHandlerFunc callback)
2842 : : {
2843 : : HandlerMatch *mlist;
2844 : 402205 : guint n_handlers = 0;
2845 : :
2846 : 402205 : mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, FALSE);
2847 : 804319 : while (mlist)
2848 : : {
2849 : 402114 : n_handlers++;
2850 : 402114 : if (mlist->handler->sequential_number)
2851 : 402114 : callback (instance, mlist->handler->sequential_number);
2852 : :
2853 : 402114 : mlist = handler_match_free1_R (mlist, instance);
2854 : : }
2855 : :
2856 : 402205 : return n_handlers;
2857 : : }
2858 : :
2859 : : /**
2860 : : * g_signal_handlers_block_matched:
2861 : : * @instance: (type GObject.Object): The instance to block handlers from.
2862 : : * @mask: Mask indicating which of @signal_id, @detail, @closure, @func
2863 : : * and/or @data the handlers have to match.
2864 : : * @signal_id: Signal the handlers have to be connected to.
2865 : : * @detail: Signal detail the handlers have to be connected to.
2866 : : * @closure: (nullable): The closure the handlers will invoke.
2867 : : * @func: The C closure callback of the handlers (useless for non-C closures).
2868 : : * @data: (nullable) (closure closure): The closure data of the handlers' closures.
2869 : : *
2870 : : * Blocks all handlers on an instance that match a certain selection criteria.
2871 : : *
2872 : : * The criteria mask is passed as a combination of #GSignalMatchType flags, and
2873 : : * the criteria values are passed as arguments. A handler must match on all
2874 : : * flags set in @mask to be blocked (i.e. the match is conjunctive).
2875 : : *
2876 : : * Passing at least one of the %G_SIGNAL_MATCH_ID, %G_SIGNAL_MATCH_CLOSURE,
2877 : : * %G_SIGNAL_MATCH_FUNC
2878 : : * or %G_SIGNAL_MATCH_DATA match flags is required for successful matches.
2879 : : * If no handlers were found, 0 is returned, the number of blocked handlers
2880 : : * otherwise.
2881 : : *
2882 : : * Support for %G_SIGNAL_MATCH_ID was added in GLib 2.78.
2883 : : *
2884 : : * Returns: The number of handlers that matched.
2885 : : */
2886 : : guint
2887 : 5 : g_signal_handlers_block_matched (gpointer instance,
2888 : : GSignalMatchType mask,
2889 : : guint signal_id,
2890 : : GQuark detail,
2891 : : GClosure *closure,
2892 : : gpointer func,
2893 : : gpointer data)
2894 : : {
2895 : 5 : guint n_handlers = 0;
2896 : :
2897 : 5 : g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
2898 : 5 : g_return_val_if_fail ((mask & (unsigned) ~G_SIGNAL_MATCH_MASK) == 0, 0);
2899 : :
2900 : 5 : if (mask & (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
2901 : : {
2902 : 5 : SIGNAL_LOCK ();
2903 : : n_handlers =
2904 : 5 : signal_handlers_foreach_matched_unlocked_R (instance, mask, signal_id, detail,
2905 : : closure, func, data,
2906 : : signal_handler_block_unlocked);
2907 : 5 : SIGNAL_UNLOCK ();
2908 : : }
2909 : :
2910 : 5 : return n_handlers;
2911 : : }
2912 : :
2913 : : /**
2914 : : * g_signal_handlers_unblock_matched:
2915 : : * @instance: (type GObject.Object): The instance to unblock handlers from.
2916 : : * @mask: Mask indicating which of @signal_id, @detail, @closure, @func
2917 : : * and/or @data the handlers have to match.
2918 : : * @signal_id: Signal the handlers have to be connected to.
2919 : : * @detail: Signal detail the handlers have to be connected to.
2920 : : * @closure: (nullable): The closure the handlers will invoke.
2921 : : * @func: The C closure callback of the handlers (useless for non-C closures).
2922 : : * @data: (nullable) (closure closure): The closure data of the handlers' closures.
2923 : : *
2924 : : * Unblocks all handlers on an instance that match a certain selection
2925 : : * criteria.
2926 : : *
2927 : : * The criteria mask is passed as a combination of #GSignalMatchType flags, and
2928 : : * the criteria values are passed as arguments. A handler must match on all
2929 : : * flags set in @mask to be unblocked (i.e. the match is conjunctive).
2930 : : *
2931 : : * Passing at least one of the %G_SIGNAL_MATCH_ID, %G_SIGNAL_MATCH_CLOSURE,
2932 : : * %G_SIGNAL_MATCH_FUNC
2933 : : * or %G_SIGNAL_MATCH_DATA match flags is required for successful matches.
2934 : : * If no handlers were found, 0 is returned, the number of unblocked handlers
2935 : : * otherwise. The match criteria should not apply to any handlers that are
2936 : : * not currently blocked.
2937 : : *
2938 : : * Support for %G_SIGNAL_MATCH_ID was added in GLib 2.78.
2939 : : *
2940 : : * Returns: The number of handlers that matched.
2941 : : */
2942 : : guint
2943 : 3 : g_signal_handlers_unblock_matched (gpointer instance,
2944 : : GSignalMatchType mask,
2945 : : guint signal_id,
2946 : : GQuark detail,
2947 : : GClosure *closure,
2948 : : gpointer func,
2949 : : gpointer data)
2950 : : {
2951 : 3 : guint n_handlers = 0;
2952 : :
2953 : 3 : g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
2954 : 3 : g_return_val_if_fail ((mask & (unsigned) ~G_SIGNAL_MATCH_MASK) == 0, 0);
2955 : :
2956 : 3 : if (mask & (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
2957 : : {
2958 : 3 : SIGNAL_LOCK ();
2959 : : n_handlers =
2960 : 3 : signal_handlers_foreach_matched_unlocked_R (instance, mask, signal_id, detail,
2961 : : closure, func, data,
2962 : : signal_handler_unblock_unlocked);
2963 : 3 : SIGNAL_UNLOCK ();
2964 : : }
2965 : :
2966 : 3 : return n_handlers;
2967 : : }
2968 : :
2969 : : /**
2970 : : * g_signal_handlers_disconnect_matched:
2971 : : * @instance: (type GObject.Object): The instance to remove handlers from.
2972 : : * @mask: Mask indicating which of @signal_id, @detail, @closure, @func
2973 : : * and/or @data the handlers have to match.
2974 : : * @signal_id: Signal the handlers have to be connected to.
2975 : : * @detail: Signal detail the handlers have to be connected to.
2976 : : * @closure: (nullable): The closure the handlers will invoke.
2977 : : * @func: The C closure callback of the handlers (useless for non-C closures).
2978 : : * @data: (nullable) (closure closure): The closure data of the handlers' closures.
2979 : : *
2980 : : * Disconnects all handlers on an instance that match a certain
2981 : : * selection criteria.
2982 : : *
2983 : : * The criteria mask is passed as a combination of #GSignalMatchType flags, and
2984 : : * the criteria values are passed as arguments. A handler must match on all
2985 : : * flags set in @mask to be disconnected (i.e. the match is conjunctive).
2986 : : *
2987 : : * Passing at least one of the %G_SIGNAL_MATCH_ID, %G_SIGNAL_MATCH_CLOSURE,
2988 : : * %G_SIGNAL_MATCH_FUNC or
2989 : : * %G_SIGNAL_MATCH_DATA match flags is required for successful
2990 : : * matches. If no handlers were found, 0 is returned, the number of
2991 : : * disconnected handlers otherwise.
2992 : : *
2993 : : * Support for %G_SIGNAL_MATCH_ID was added in GLib 2.78.
2994 : : *
2995 : : * Returns: The number of handlers that matched.
2996 : : */
2997 : : guint
2998 : 402197 : g_signal_handlers_disconnect_matched (gpointer instance,
2999 : : GSignalMatchType mask,
3000 : : guint signal_id,
3001 : : GQuark detail,
3002 : : GClosure *closure,
3003 : : gpointer func,
3004 : : gpointer data)
3005 : : {
3006 : 402197 : guint n_handlers = 0;
3007 : :
3008 : 402197 : g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
3009 : 402197 : g_return_val_if_fail ((mask & (unsigned) ~G_SIGNAL_MATCH_MASK) == 0, 0);
3010 : :
3011 : 402197 : if (mask & (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
3012 : : {
3013 : 402197 : SIGNAL_LOCK ();
3014 : : n_handlers =
3015 : 402197 : signal_handlers_foreach_matched_unlocked_R (instance, mask, signal_id, detail,
3016 : : closure, func, data,
3017 : : signal_handler_disconnect_unlocked);
3018 : 402197 : SIGNAL_UNLOCK ();
3019 : : }
3020 : :
3021 : 402197 : return n_handlers;
3022 : : }
3023 : :
3024 : : /**
3025 : : * g_signal_has_handler_pending:
3026 : : * @instance: (type GObject.Object): the object whose signal handlers are sought.
3027 : : * @signal_id: the signal id.
3028 : : * @detail: the detail.
3029 : : * @may_be_blocked: whether blocked handlers should count as match.
3030 : : *
3031 : : * Returns whether there are any handlers connected to @instance for the
3032 : : * given signal id and detail.
3033 : : *
3034 : : * If @detail is 0 then it will only match handlers that were connected
3035 : : * without detail. If @detail is non-zero then it will match handlers
3036 : : * connected both without detail and with the given detail. This is
3037 : : * consistent with how a signal emitted with @detail would be delivered
3038 : : * to those handlers.
3039 : : *
3040 : : * Since 2.46 this also checks for a non-default class closure being
3041 : : * installed, as this is basically always what you want.
3042 : : *
3043 : : * One example of when you might use this is when the arguments to the
3044 : : * signal are difficult to compute. A class implementor may opt to not
3045 : : * emit the signal if no one is attached anyway, thus saving the cost
3046 : : * of building the arguments.
3047 : : *
3048 : : * Returns: %TRUE if a handler is connected to the signal, %FALSE
3049 : : * otherwise.
3050 : : */
3051 : : gboolean
3052 : 147 : g_signal_has_handler_pending (gpointer instance,
3053 : : guint signal_id,
3054 : : GQuark detail,
3055 : : gboolean may_be_blocked)
3056 : : {
3057 : : HandlerMatch *mlist;
3058 : : gboolean has_pending;
3059 : : SignalNode *node;
3060 : :
3061 : 147 : g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
3062 : 147 : g_return_val_if_fail (signal_id > 0, FALSE);
3063 : :
3064 : 147 : SIGNAL_LOCK ();
3065 : :
3066 : 147 : node = LOOKUP_SIGNAL_NODE (signal_id);
3067 : 147 : if (detail)
3068 : : {
3069 : 0 : if (!(node->flags & G_SIGNAL_DETAILED))
3070 : : {
3071 : 0 : g_critical ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
3072 : 0 : SIGNAL_UNLOCK ();
3073 : 0 : return FALSE;
3074 : : }
3075 : : }
3076 : 147 : mlist = handlers_find (instance,
3077 : : (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | (may_be_blocked ? 0 : G_SIGNAL_MATCH_UNBLOCKED)),
3078 : : signal_id, detail, NULL, NULL, NULL, TRUE);
3079 : 147 : if (mlist)
3080 : : {
3081 : 80 : has_pending = TRUE;
3082 : 80 : handler_match_free1_R (mlist, instance);
3083 : : }
3084 : : else
3085 : : {
3086 : 67 : ClassClosure *class_closure = signal_find_class_closure (node, G_TYPE_FROM_INSTANCE (instance));
3087 : 67 : if (class_closure != NULL && class_closure->instance_type != 0)
3088 : 0 : has_pending = TRUE;
3089 : : else
3090 : 67 : has_pending = FALSE;
3091 : : }
3092 : 147 : SIGNAL_UNLOCK ();
3093 : :
3094 : 147 : return has_pending;
3095 : : }
3096 : :
3097 : : static void
3098 : : signal_emitv_unlocked (const GValue *instance_and_params,
3099 : : guint signal_id,
3100 : : GQuark detail,
3101 : : GValue *return_value);
3102 : :
3103 : : /**
3104 : : * g_signal_emitv:
3105 : : * @instance_and_params: (array): argument list for the signal emission.
3106 : : * The first element in the array is a #GValue for the instance the signal
3107 : : * is being emitted on. The rest are any arguments to be passed to the signal.
3108 : : * @signal_id: the signal id
3109 : : * @detail: the detail
3110 : : * @return_value: (inout) (optional): Location to
3111 : : * store the return value of the signal emission. This must be provided if the
3112 : : * specified signal returns a value, but may be ignored otherwise.
3113 : : *
3114 : : * Emits a signal. Signal emission is done synchronously.
3115 : : * The method will only return control after all handlers are called or signal emission was stopped.
3116 : : *
3117 : : * Note that g_signal_emitv() doesn't change @return_value if no handlers are
3118 : : * connected, in contrast to g_signal_emit() and g_signal_emit_valist().
3119 : : */
3120 : : void
3121 : 73 : g_signal_emitv (const GValue *instance_and_params,
3122 : : guint signal_id,
3123 : : GQuark detail,
3124 : : GValue *return_value)
3125 : : {
3126 : 73 : SIGNAL_LOCK ();
3127 : 73 : signal_emitv_unlocked (instance_and_params, signal_id, detail, return_value);
3128 : 73 : SIGNAL_UNLOCK ();
3129 : 73 : }
3130 : :
3131 : : static void
3132 : 73 : signal_emitv_unlocked (const GValue *instance_and_params,
3133 : : guint signal_id,
3134 : : GQuark detail,
3135 : : GValue *return_value)
3136 : : {
3137 : : gpointer instance;
3138 : : SignalNode *node;
3139 : : #ifdef G_ENABLE_DEBUG
3140 : : const GValue *param_values;
3141 : : guint i;
3142 : : #endif
3143 : :
3144 : 75 : g_return_if_fail (instance_and_params != NULL);
3145 : 73 : instance = g_value_peek_pointer (instance_and_params);
3146 : 73 : g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
3147 : 73 : g_return_if_fail (signal_id > 0);
3148 : :
3149 : : #ifdef G_ENABLE_DEBUG
3150 : 73 : param_values = instance_and_params + 1;
3151 : : #endif
3152 : :
3153 : 73 : node = LOOKUP_SIGNAL_NODE (signal_id);
3154 : 73 : if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
3155 : : {
3156 : 0 : g_critical ("%s: signal id '%u' is invalid for instance '%p'", G_STRLOC, signal_id, instance);
3157 : 0 : return;
3158 : : }
3159 : : #ifdef G_ENABLE_DEBUG
3160 : 73 : if (detail && !(node->flags & G_SIGNAL_DETAILED))
3161 : : {
3162 : 0 : g_critical ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
3163 : 0 : return;
3164 : : }
3165 : 319 : for (i = 0; i < node->n_params; i++)
3166 : 246 : if (!G_TYPE_CHECK_VALUE_TYPE (param_values + i, node->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE))
3167 : : {
3168 : 0 : g_critical ("%s: value for '%s' parameter %u for signal \"%s\" is of type '%s'",
3169 : : G_STRLOC,
3170 : : type_debug_name (node->param_types[i]),
3171 : : i,
3172 : : node->name,
3173 : : G_VALUE_TYPE_NAME (param_values + i));
3174 : 0 : return;
3175 : : }
3176 : 73 : if (node->return_type != G_TYPE_NONE)
3177 : : {
3178 : 62 : if (!return_value)
3179 : : {
3180 : 1 : g_critical ("%s: return value '%s' for signal \"%s\" is (NULL)",
3181 : : G_STRLOC,
3182 : : type_debug_name (node->return_type),
3183 : : node->name);
3184 : 1 : return;
3185 : : }
3186 : 61 : else if (!node->accumulator && !G_TYPE_CHECK_VALUE_TYPE (return_value, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE))
3187 : : {
3188 : 1 : g_critical ("%s: return value '%s' for signal \"%s\" is of type '%s'",
3189 : : G_STRLOC,
3190 : : type_debug_name (node->return_type),
3191 : : node->name,
3192 : : G_VALUE_TYPE_NAME (return_value));
3193 : 1 : return;
3194 : : }
3195 : : }
3196 : : else
3197 : 11 : return_value = NULL;
3198 : : #endif /* G_ENABLE_DEBUG */
3199 : :
3200 : : /* optimize NOP emissions */
3201 : 71 : if (!node->single_va_closure_is_valid)
3202 : 42 : node_update_single_va_closure (node);
3203 : :
3204 : 71 : if (node->single_va_closure != NULL &&
3205 : 0 : (node->single_va_closure == SINGLE_VA_CLOSURE_EMPTY_MAGIC ||
3206 : 0 : _g_closure_is_void (node->single_va_closure, instance)))
3207 : : {
3208 : : HandlerList* hlist;
3209 : :
3210 : : /* single_va_closure is only true for GObjects, so fast path if no handler ever connected to the signal */
3211 : 0 : if (_g_object_has_signal_handler ((GObject *)instance))
3212 : 0 : hlist = handler_list_lookup (node->signal_id, instance);
3213 : : else
3214 : 0 : hlist = NULL;
3215 : :
3216 : 0 : if (hlist == NULL || hlist->handlers == NULL)
3217 : : {
3218 : : /* nothing to do to emit this signal */
3219 : : /* g_printerr ("omitting emission of \"%s\"\n", node->name); */
3220 : 0 : return;
3221 : : }
3222 : : }
3223 : :
3224 : : /* Pass a stable node pointer, whose address can't change even if the
3225 : : * g_signal_nodes array gets reallocated. */
3226 : 71 : SignalNode node_copy = *node;
3227 : 71 : signal_emit_unlocked_R (&node_copy, detail, instance, return_value, instance_and_params);
3228 : : }
3229 : :
3230 : : static inline gboolean
3231 : 15876562 : accumulate (GSignalInvocationHint *ihint,
3232 : : GValue *return_accu,
3233 : : GValue *handler_return,
3234 : : SignalAccumulator *accumulator)
3235 : : {
3236 : : gboolean continue_emission;
3237 : :
3238 : 15876562 : if (!accumulator)
3239 : 15874222 : return TRUE;
3240 : :
3241 : 2340 : continue_emission = accumulator->func (ihint, return_accu, handler_return, accumulator->data);
3242 : 2340 : g_value_reset (handler_return);
3243 : :
3244 : 2340 : ihint->run_type &= (unsigned) ~G_SIGNAL_ACCUMULATOR_FIRST_RUN;
3245 : :
3246 : 2340 : return continue_emission;
3247 : : }
3248 : :
3249 : : static gboolean
3250 : : signal_emit_valist_unlocked (gpointer instance,
3251 : : guint signal_id,
3252 : : GQuark detail,
3253 : : va_list var_args);
3254 : :
3255 : : /**
3256 : : * g_signal_emit_valist: (skip)
3257 : : * @instance: (type GObject.TypeInstance): the instance the signal is being
3258 : : * emitted on.
3259 : : * @signal_id: the signal id
3260 : : * @detail: the detail
3261 : : * @var_args: a list of parameters to be passed to the signal, followed by a
3262 : : * location for the return value. If the return type of the signal
3263 : : * is %G_TYPE_NONE, the return value location can be omitted.
3264 : : *
3265 : : * Emits a signal. Signal emission is done synchronously.
3266 : : * The method will only return control after all handlers are called or signal emission was stopped.
3267 : : *
3268 : : * Note that g_signal_emit_valist() resets the return value to the default
3269 : : * if no handlers are connected, in contrast to g_signal_emitv().
3270 : : */
3271 : : void
3272 : 19128528 : g_signal_emit_valist (gpointer instance,
3273 : : guint signal_id,
3274 : : GQuark detail,
3275 : : va_list var_args)
3276 : : {
3277 : 19128528 : SIGNAL_LOCK ();
3278 : 19128528 : if (signal_emit_valist_unlocked (instance, signal_id, detail, var_args))
3279 : 9635380 : SIGNAL_UNLOCK ();
3280 : 19128520 : }
3281 : :
3282 : : /*<private>
3283 : : * signal_emit_valist_unlocked:
3284 : : * @instance: The instance to emit from
3285 : : * @signal_id: Signal id to emit
3286 : : * @detail: Signal detail
3287 : : * @var_args: Call arguments
3288 : : *
3289 : : * Returns: %TRUE if the signal mutex has been left locked
3290 : : */
3291 : : static gboolean
3292 : 19128971 : signal_emit_valist_unlocked (gpointer instance,
3293 : : guint signal_id,
3294 : : GQuark detail,
3295 : : va_list var_args)
3296 : : {
3297 : : GValue *instance_and_params;
3298 : : GValue *param_values;
3299 : : SignalNode *node;
3300 : : guint i;
3301 : :
3302 : 19128971 : g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), TRUE);
3303 : 19128971 : g_return_val_if_fail (signal_id > 0, TRUE);
3304 : :
3305 : 19128971 : node = LOOKUP_SIGNAL_NODE (signal_id);
3306 : 19128971 : if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
3307 : : {
3308 : 0 : g_critical ("%s: signal id '%u' is invalid for instance '%p'", G_STRLOC, signal_id, instance);
3309 : 0 : return TRUE;
3310 : : }
3311 : : #ifndef G_DISABLE_CHECKS
3312 : 19128971 : if (detail && !(node->flags & G_SIGNAL_DETAILED))
3313 : : {
3314 : 0 : g_critical ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
3315 : 0 : return TRUE;
3316 : : }
3317 : : #endif /* !G_DISABLE_CHECKS */
3318 : :
3319 : 19128971 : if (!node->single_va_closure_is_valid)
3320 : 468 : node_update_single_va_closure (node);
3321 : :
3322 : : /* There's no need to deep copy this, because a SignalNode instance won't
3323 : : * ever be destroyed, given that _g_signals_destroy() is not called in any
3324 : : * real program, however the SignalNode pointer could change, so just store
3325 : : * the struct contents references, so that we won't try to deference a
3326 : : * potentially invalid (or changed) pointer;
3327 : : */
3328 : 19128971 : SignalNode node_copy = *node;
3329 : :
3330 : 19128971 : if (node->single_va_closure != NULL)
3331 : : {
3332 : : HandlerList* hlist;
3333 : 19026297 : Handler *fastpath_handler = NULL;
3334 : : Handler *l;
3335 : 19026297 : GClosure *closure = NULL;
3336 : 19026297 : gboolean fastpath = TRUE;
3337 : 19026297 : GSignalFlags run_type = G_SIGNAL_RUN_FIRST;
3338 : :
3339 : 37721798 : if (node->single_va_closure != SINGLE_VA_CLOSURE_EMPTY_MAGIC &&
3340 : 18695501 : !_g_closure_is_void (node->single_va_closure, instance))
3341 : : {
3342 : 4546636 : if (_g_closure_supports_invoke_va (node->single_va_closure))
3343 : : {
3344 : 677896 : closure = node->single_va_closure;
3345 : 677896 : if (node->single_va_closure_is_after)
3346 : 1893 : run_type = G_SIGNAL_RUN_LAST;
3347 : : else
3348 : 676003 : run_type = G_SIGNAL_RUN_FIRST;
3349 : : }
3350 : : else
3351 : 3868740 : fastpath = FALSE;
3352 : : }
3353 : :
3354 : : /* single_va_closure is only true for GObjects, so fast path if no handler ever connected to the signal */
3355 : 19026297 : if (_g_object_has_signal_handler ((GObject *)instance))
3356 : 7691418 : hlist = handler_list_lookup (node->signal_id, instance);
3357 : : else
3358 : 11334879 : hlist = NULL;
3359 : :
3360 : 22808520 : for (l = hlist ? hlist->handlers : NULL; fastpath && l != NULL; l = l->next)
3361 : : {
3362 : 5674960 : if (!l->block_count &&
3363 : 5674677 : (!l->detail || l->detail == detail))
3364 : : {
3365 : 5085273 : if (closure != NULL || !_g_closure_supports_invoke_va (l->closure))
3366 : : {
3367 : 1892737 : fastpath = FALSE;
3368 : 1892737 : break;
3369 : : }
3370 : : else
3371 : : {
3372 : 3192536 : fastpath_handler = l;
3373 : 3192536 : closure = l->closure;
3374 : 3192536 : if (l->after)
3375 : 0 : run_type = G_SIGNAL_RUN_LAST;
3376 : : else
3377 : 3192536 : run_type = G_SIGNAL_RUN_FIRST;
3378 : : }
3379 : : }
3380 : : }
3381 : :
3382 : 19026297 : if (fastpath && closure == NULL && node_copy.return_type == G_TYPE_NONE)
3383 : 9635557 : return TRUE;
3384 : :
3385 : : /* Don't allow no-recurse emission as we might have to restart, which means
3386 : : we will run multiple handlers and thus must ref all arguments */
3387 : 9390740 : if (closure != NULL && (node_copy.flags & (G_SIGNAL_NO_RECURSE)) != 0)
3388 : 2660624 : fastpath = FALSE;
3389 : :
3390 : 9390740 : if (fastpath)
3391 : : {
3392 : : Emission emission;
3393 : 968658 : GValue *return_accu, accu = G_VALUE_INIT;
3394 : 968658 : GType instance_type = G_TYPE_FROM_INSTANCE (instance);
3395 : 968658 : GValue emission_return = G_VALUE_INIT;
3396 : 968658 : GType rtype = node_copy.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE;
3397 : 968658 : gboolean static_scope = node_copy.return_type & G_SIGNAL_TYPE_STATIC_SCOPE;
3398 : :
3399 : 968658 : if (rtype == G_TYPE_NONE)
3400 : 967772 : return_accu = NULL;
3401 : 886 : else if (node_copy.accumulator)
3402 : 871 : return_accu = &accu;
3403 : : else
3404 : 15 : return_accu = &emission_return;
3405 : :
3406 : 968658 : emission.instance = instance;
3407 : 968658 : emission.ihint.signal_id = signal_id;
3408 : 968658 : emission.ihint.detail = detail;
3409 : 968658 : emission.ihint.run_type = run_type | G_SIGNAL_ACCUMULATOR_FIRST_RUN;
3410 : 968658 : emission.state = EMISSION_RUN;
3411 : 968658 : emission.chain_type = instance_type;
3412 : 968658 : emission_push (&emission);
3413 : :
3414 : 968658 : if (fastpath_handler)
3415 : 531982 : handler_ref (fastpath_handler);
3416 : :
3417 : 968658 : if (closure != NULL)
3418 : : {
3419 : 968658 : TRACE (GOBJECT_SIGNAL_EMIT (signal_id, detail, instance, (uintmax_t) instance_type));
3420 : :
3421 : 968658 : SIGNAL_UNLOCK ();
3422 : :
3423 : 968658 : if (rtype != G_TYPE_NONE)
3424 : 886 : g_value_init (&emission_return, rtype);
3425 : :
3426 : 968658 : if (node_copy.accumulator)
3427 : 871 : g_value_init (&accu, rtype);
3428 : :
3429 : : /*
3430 : : * Coverity doesn’t understand the paired ref/unref here and seems
3431 : : * to ignore the ref, thus reports every call to g_signal_emit()
3432 : : * as causing a double-free. That’s incorrect, but I can’t get a
3433 : : * model file to work for avoiding the false positives, so instead
3434 : : * comment out the ref/unref when doing static analysis.
3435 : : */
3436 : : #ifndef __COVERITY__
3437 : 968658 : g_object_ref (instance);
3438 : : #endif
3439 : 968658 : _g_closure_invoke_va (closure,
3440 : : return_accu,
3441 : : instance,
3442 : : var_args,
3443 : 968658 : node_copy.n_params,
3444 : : node_copy.param_types);
3445 : 968656 : accumulate (&emission.ihint, &emission_return, &accu, node_copy.accumulator);
3446 : :
3447 : 968656 : if (node_copy.accumulator)
3448 : 871 : g_value_unset (&accu);
3449 : :
3450 : 968656 : SIGNAL_LOCK ();
3451 : : }
3452 : :
3453 : 968656 : emission.chain_type = G_TYPE_NONE;
3454 : 968656 : emission_pop (&emission);
3455 : :
3456 : 968656 : if (fastpath_handler)
3457 : 531980 : handler_unref_R (signal_id, instance, fastpath_handler);
3458 : :
3459 : 968656 : SIGNAL_UNLOCK ();
3460 : :
3461 : 968656 : if (rtype != G_TYPE_NONE)
3462 : : {
3463 : 886 : gchar *error = NULL;
3464 : 2352 : for (i = 0; i < node_copy.n_params; i++)
3465 : : {
3466 : 1466 : GType ptype = node_copy.param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE;
3467 : 2932 : G_VALUE_COLLECT_SKIP (ptype, var_args);
3468 : : }
3469 : :
3470 : 886 : if (closure == NULL)
3471 : 0 : g_value_init (&emission_return, rtype);
3472 : :
3473 : 1772 : G_VALUE_LCOPY (&emission_return,
3474 : : var_args,
3475 : : static_scope ? G_VALUE_NOCOPY_CONTENTS : 0,
3476 : : &error);
3477 : 886 : if (!error)
3478 : 886 : g_value_unset (&emission_return);
3479 : : else
3480 : : {
3481 : 0 : g_critical ("%s: %s", G_STRLOC, error);
3482 : 0 : g_free (error);
3483 : : /* we purposely leak the value here, it might not be
3484 : : * in a correct state if an error condition occurred
3485 : : */
3486 : : }
3487 : : }
3488 : :
3489 : 968656 : TRACE (GOBJECT_SIGNAL_EMIT_END (signal_id, detail, instance, (uintmax_t) instance_type));
3490 : :
3491 : : /* See comment above paired ref above */
3492 : : #ifndef __COVERITY__
3493 : 968656 : if (closure != NULL)
3494 : 968656 : g_object_unref (instance);
3495 : : #endif
3496 : :
3497 : 968656 : return FALSE;
3498 : : }
3499 : : }
3500 : :
3501 : 8524756 : SIGNAL_UNLOCK ();
3502 : :
3503 : 8524756 : instance_and_params = g_newa0 (GValue, node_copy.n_params + 1);
3504 : 8524756 : param_values = instance_and_params + 1;
3505 : :
3506 : 16622076 : for (i = 0; i < node_copy.n_params; i++)
3507 : : {
3508 : : gchar *error;
3509 : 8097320 : GType ptype = node_copy.param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE;
3510 : 8097320 : gboolean static_scope = node_copy.param_types[i] & G_SIGNAL_TYPE_STATIC_SCOPE;
3511 : :
3512 : 16194640 : G_VALUE_COLLECT_INIT (param_values + i, ptype,
3513 : : var_args,
3514 : : static_scope ? G_VALUE_NOCOPY_CONTENTS : 0,
3515 : : &error);
3516 : 8097320 : if (error)
3517 : : {
3518 : 0 : g_critical ("%s: %s", G_STRLOC, error);
3519 : 0 : g_free (error);
3520 : :
3521 : : /* we purposely leak the value here, it might not be
3522 : : * in a correct state if an error condition occurred
3523 : : */
3524 : 0 : while (i--)
3525 : 0 : g_value_unset (param_values + i);
3526 : :
3527 : 0 : return FALSE;
3528 : : }
3529 : : }
3530 : :
3531 : 8524756 : g_value_init_from_instance (instance_and_params, instance);
3532 : 8524756 : if (node_copy.return_type == G_TYPE_NONE)
3533 : : {
3534 : 7693295 : SIGNAL_LOCK ();
3535 : 7693295 : signal_emit_unlocked_R (&node_copy, detail, instance, NULL, instance_and_params);
3536 : 7693289 : SIGNAL_UNLOCK ();
3537 : : }
3538 : : else
3539 : : {
3540 : 831461 : GValue return_value = G_VALUE_INIT;
3541 : 831461 : gchar *error = NULL;
3542 : 831461 : GType rtype = node_copy.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE;
3543 : 831461 : gboolean static_scope = node_copy.return_type & G_SIGNAL_TYPE_STATIC_SCOPE;
3544 : :
3545 : 831461 : g_value_init (&return_value, rtype);
3546 : :
3547 : 831461 : SIGNAL_LOCK ();
3548 : 831461 : signal_emit_unlocked_R (&node_copy, detail, instance, &return_value, instance_and_params);
3549 : 831461 : SIGNAL_UNLOCK ();
3550 : :
3551 : 1662922 : G_VALUE_LCOPY (&return_value,
3552 : : var_args,
3553 : : static_scope ? G_VALUE_NOCOPY_CONTENTS : 0,
3554 : : &error);
3555 : 831461 : if (!error)
3556 : 831461 : g_value_unset (&return_value);
3557 : : else
3558 : : {
3559 : 0 : g_critical ("%s: %s", G_STRLOC, error);
3560 : 0 : g_free (error);
3561 : :
3562 : : /* we purposely leak the value here, it might not be
3563 : : * in a correct state if an error condition occurred
3564 : : */
3565 : : }
3566 : : }
3567 : 16622058 : for (i = 0; i < node_copy.n_params; i++)
3568 : 8097308 : g_value_unset (param_values + i);
3569 : 8524750 : g_value_unset (instance_and_params);
3570 : :
3571 : 8524750 : return FALSE;
3572 : : }
3573 : :
3574 : : /**
3575 : : * g_signal_emit:
3576 : : * @instance: (type GObject.Object): the instance the signal is being emitted on.
3577 : : * @signal_id: the signal id
3578 : : * @detail: the detail
3579 : : * @...: parameters to be passed to the signal, followed by a
3580 : : * location for the return value. If the return type of the signal
3581 : : * is %G_TYPE_NONE, the return value location can be omitted.
3582 : : *
3583 : : * Emits a signal. Signal emission is done synchronously.
3584 : : * The method will only return control after all handlers are called or signal emission was stopped.
3585 : : *
3586 : : * Note that g_signal_emit() resets the return value to the default
3587 : : * if no handlers are connected, in contrast to g_signal_emitv().
3588 : : */
3589 : : void
3590 : 19128528 : g_signal_emit (gpointer instance,
3591 : : guint signal_id,
3592 : : GQuark detail,
3593 : : ...)
3594 : : {
3595 : : va_list var_args;
3596 : :
3597 : 19128528 : va_start (var_args, detail);
3598 : 19128528 : g_signal_emit_valist (instance, signal_id, detail, var_args);
3599 : 19128520 : va_end (var_args);
3600 : 19128520 : }
3601 : :
3602 : : /**
3603 : : * g_signal_emit_by_name:
3604 : : * @instance: (type GObject.Object): the instance the signal is being emitted on.
3605 : : * @detailed_signal: a string of the form "signal-name::detail".
3606 : : * @...: parameters to be passed to the signal, followed by a
3607 : : * location for the return value. If the return type of the signal
3608 : : * is %G_TYPE_NONE, the return value location can be omitted. The
3609 : : * number of parameters to pass to this function is defined when creating the signal.
3610 : : *
3611 : : * Emits a signal. Signal emission is done synchronously.
3612 : : * The method will only return control after all handlers are called or signal emission was stopped.
3613 : : *
3614 : : * Note that g_signal_emit_by_name() resets the return value to the default
3615 : : * if no handlers are connected, in contrast to g_signal_emitv().
3616 : : */
3617 : : void
3618 : 443 : g_signal_emit_by_name (gpointer instance,
3619 : : const gchar *detailed_signal,
3620 : : ...)
3621 : : {
3622 : 443 : GQuark detail = 0;
3623 : : guint signal_id;
3624 : : GType itype;
3625 : :
3626 : 443 : g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
3627 : 443 : g_return_if_fail (detailed_signal != NULL);
3628 : :
3629 : 443 : itype = G_TYPE_FROM_INSTANCE (instance);
3630 : :
3631 : 443 : SIGNAL_LOCK ();
3632 : 443 : signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
3633 : :
3634 : 443 : if (signal_id)
3635 : : {
3636 : : va_list var_args;
3637 : :
3638 : 443 : va_start (var_args, detailed_signal);
3639 : 443 : if (signal_emit_valist_unlocked (instance, signal_id, detail, var_args))
3640 : 177 : SIGNAL_UNLOCK ();
3641 : 443 : va_end (var_args);
3642 : : }
3643 : : else
3644 : : {
3645 : 0 : SIGNAL_UNLOCK ();
3646 : :
3647 : 0 : g_critical ("%s: signal name '%s' is invalid for instance '%p' of type '%s'",
3648 : : G_STRLOC, detailed_signal, instance, g_type_name (itype));
3649 : : }
3650 : : }
3651 : :
3652 : : G_ALWAYS_INLINE static inline GValue *
3653 : : maybe_init_accumulator_unlocked (SignalNode *node,
3654 : : GValue *emission_return,
3655 : : GValue *accumulator_value)
3656 : : {
3657 : 14907908 : if (node->accumulator)
3658 : : {
3659 : 1465 : if (accumulator_value->g_type)
3660 : 564 : return accumulator_value;
3661 : :
3662 : 901 : g_value_init (accumulator_value,
3663 : 901 : node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
3664 : 901 : return accumulator_value;
3665 : : }
3666 : :
3667 : 14906443 : return emission_return;
3668 : : }
3669 : :
3670 : : static gboolean
3671 : 8524827 : signal_emit_unlocked_R (SignalNode *node,
3672 : : GQuark detail,
3673 : : gpointer instance,
3674 : : GValue *emission_return,
3675 : : const GValue *instance_and_params)
3676 : : {
3677 : : SignalAccumulator *accumulator;
3678 : : Emission emission;
3679 : : GClosure *class_closure;
3680 : : HandlerList *hlist;
3681 : 8524827 : Handler *handler_list = NULL;
3682 : 8524827 : GValue *return_accu, accu = G_VALUE_INIT;
3683 : : guint signal_id;
3684 : : gulong max_sequential_handler_number;
3685 : 8524827 : gboolean return_value_altered = FALSE;
3686 : : guint n_params;
3687 : :
3688 : 8524827 : TRACE(GOBJECT_SIGNAL_EMIT(node->signal_id, detail, instance, G_TYPE_FROM_INSTANCE (instance)));
3689 : :
3690 : : /* We expect this function to be called with a stable SignalNode pointer
3691 : : * that cannot change location, so accessing its stable members should
3692 : : * always work even after a lock/unlock.
3693 : : */
3694 : 8524827 : signal_id = node->signal_id;
3695 : 8524827 : n_params = node->n_params + 1;
3696 : :
3697 : 8524827 : if (node->flags & G_SIGNAL_NO_RECURSE)
3698 : : {
3699 : 2660624 : Emission *emission_node = emission_find (signal_id, detail, instance);
3700 : :
3701 : 2660624 : if (emission_node)
3702 : : {
3703 : 136265 : emission_node->state = EMISSION_RESTART;
3704 : 136265 : return return_value_altered;
3705 : : }
3706 : : }
3707 : 8388562 : accumulator = node->accumulator;
3708 : 8388562 : emission.instance = instance;
3709 : 8388562 : emission.ihint.signal_id = node->signal_id;
3710 : 8388562 : emission.ihint.detail = detail;
3711 : 8388562 : emission.ihint.run_type = 0;
3712 : 8388562 : emission.state = 0;
3713 : 8388562 : emission.chain_type = G_TYPE_NONE;
3714 : 8388562 : emission_push (&emission);
3715 : 8388562 : class_closure = signal_lookup_closure (node, instance);
3716 : :
3717 : 87750 : EMIT_RESTART:
3718 : :
3719 : 8476312 : if (handler_list)
3720 : 87750 : handler_unref_R (signal_id, instance, handler_list);
3721 : 8476312 : max_sequential_handler_number = g_handler_sequential_number;
3722 : 8476312 : hlist = handler_list_lookup (signal_id, instance);
3723 : 8476312 : handler_list = hlist ? hlist->handlers : NULL;
3724 : 8476312 : if (handler_list)
3725 : 6495126 : handler_ref (handler_list);
3726 : :
3727 : 8476312 : emission.ihint.run_type = G_SIGNAL_RUN_FIRST | G_SIGNAL_ACCUMULATOR_FIRST_RUN;
3728 : :
3729 : 8476312 : if ((node->flags & G_SIGNAL_RUN_FIRST) && class_closure)
3730 : : {
3731 : 4215384 : emission.state = EMISSION_RUN;
3732 : :
3733 : 4215384 : emission.chain_type = G_TYPE_FROM_INSTANCE (instance);
3734 : 4215384 : SIGNAL_UNLOCK ();
3735 : 4215384 : return_accu = maybe_init_accumulator_unlocked (node, emission_return, &accu);
3736 : 4215384 : g_closure_invoke (class_closure,
3737 : : return_accu,
3738 : : n_params,
3739 : : instance_and_params,
3740 : : &emission.ihint);
3741 : 4215384 : if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) &&
3742 : 0 : emission.state == EMISSION_RUN)
3743 : 0 : emission.state = EMISSION_STOP;
3744 : 4215384 : SIGNAL_LOCK ();
3745 : 4215384 : emission.chain_type = G_TYPE_NONE;
3746 : 4215384 : return_value_altered = TRUE;
3747 : :
3748 : 4215384 : if (emission.state == EMISSION_STOP)
3749 : 0 : goto EMIT_CLEANUP;
3750 : 4215384 : else if (emission.state == EMISSION_RESTART)
3751 : 44853 : goto EMIT_RESTART;
3752 : : }
3753 : :
3754 : 8431459 : if (node->emission_hooks)
3755 : : {
3756 : : GHook *hook;
3757 : : GHook *static_emission_hooks[3];
3758 : 14 : size_t n_emission_hooks = 0;
3759 : 14 : const gboolean may_recurse = TRUE;
3760 : : guint i;
3761 : :
3762 : 14 : emission.state = EMISSION_HOOK;
3763 : :
3764 : : /* Quick check to determine whether any hooks match this emission,
3765 : : * before committing to the more complex work of calling those hooks.
3766 : : * We save a few of them into a static array, to try to avoid further
3767 : : * allocations.
3768 : : */
3769 : 14 : hook = g_hook_first_valid (node->emission_hooks, may_recurse);
3770 : 51 : while (hook)
3771 : : {
3772 : 37 : SignalHook *signal_hook = SIGNAL_HOOK (hook);
3773 : :
3774 : 37 : if (!signal_hook->detail || signal_hook->detail == detail)
3775 : : {
3776 : 37 : if (n_emission_hooks < G_N_ELEMENTS (static_emission_hooks))
3777 : : {
3778 : 16 : static_emission_hooks[n_emission_hooks] =
3779 : 16 : g_hook_ref (node->emission_hooks, hook);
3780 : : }
3781 : :
3782 : 37 : n_emission_hooks += 1;
3783 : : }
3784 : :
3785 : 37 : hook = g_hook_next_valid (node->emission_hooks, hook, may_recurse);
3786 : : }
3787 : :
3788 : : /* Re-iterate back through the matching hooks and copy them into
3789 : : * an array which won’t change when we unlock to call the
3790 : : * user-provided hook functions.
3791 : : * These functions may change hook configuration for this signal,
3792 : : * add / remove signal handlers, etc.
3793 : : */
3794 : 14 : if G_UNLIKELY (n_emission_hooks > 0)
3795 : : {
3796 : : guint8 static_hook_returns[G_N_ELEMENTS (static_emission_hooks)];
3797 : 10 : GHook **emission_hooks = NULL;
3798 : 10 : guint8 *hook_returns = NULL;
3799 : :
3800 : 10 : if G_LIKELY (n_emission_hooks <= G_N_ELEMENTS (static_emission_hooks))
3801 : : {
3802 : 7 : emission_hooks = static_emission_hooks;
3803 : 7 : hook_returns = static_hook_returns;
3804 : : }
3805 : : else
3806 : : {
3807 : 3 : emission_hooks = g_newa (GHook *, n_emission_hooks);
3808 : 3 : hook_returns = g_newa (guint8, n_emission_hooks);
3809 : :
3810 : : /* We can't just memcpy the ones we have in the static array,
3811 : : * to the alloca()'d one because otherwise we'd get an invalid
3812 : : * ID assertion during unref
3813 : : */
3814 : 3 : i = 0;
3815 : 3 : for (hook = g_hook_first_valid (node->emission_hooks, may_recurse);
3816 : 33 : hook != NULL;
3817 : 30 : hook = g_hook_next_valid (node->emission_hooks, hook, may_recurse))
3818 : : {
3819 : 30 : SignalHook *signal_hook = SIGNAL_HOOK (hook);
3820 : :
3821 : 30 : if (!signal_hook->detail || signal_hook->detail == detail)
3822 : : {
3823 : 30 : if (i < G_N_ELEMENTS (static_emission_hooks))
3824 : : {
3825 : 9 : emission_hooks[i] = g_steal_pointer (&static_emission_hooks[i]);
3826 : 9 : g_assert (emission_hooks[i] == hook);
3827 : : }
3828 : : else
3829 : : {
3830 : 21 : emission_hooks[i] = g_hook_ref (node->emission_hooks, hook);
3831 : : }
3832 : :
3833 : 30 : i += 1;
3834 : : }
3835 : : }
3836 : :
3837 : 3 : g_assert (i == n_emission_hooks);
3838 : : }
3839 : :
3840 : 10 : SIGNAL_UNLOCK ();
3841 : :
3842 : 47 : for (i = 0; i < n_emission_hooks; ++i)
3843 : : {
3844 : : GSignalEmissionHook hook_func;
3845 : : gboolean need_destroy;
3846 : : guint old_flags;
3847 : :
3848 : 37 : hook = emission_hooks[i];
3849 : 37 : hook_func = (GSignalEmissionHook) hook->func;
3850 : :
3851 : 37 : old_flags = g_atomic_int_or (&hook->flags, G_HOOK_FLAG_IN_CALL);
3852 : 37 : need_destroy = !hook_func (&emission.ihint, n_params,
3853 : : instance_and_params, hook->data);
3854 : :
3855 : 37 : if (!(old_flags & G_HOOK_FLAG_IN_CALL))
3856 : : {
3857 : 37 : g_atomic_int_compare_and_exchange ((gint *) &hook->flags,
3858 : : (gint) old_flags | G_HOOK_FLAG_IN_CALL,
3859 : : (gint) old_flags);
3860 : : }
3861 : :
3862 : 37 : hook_returns[i] = !!need_destroy;
3863 : : }
3864 : :
3865 : 10 : SIGNAL_LOCK ();
3866 : :
3867 : 47 : for (i = 0; i < n_emission_hooks; i++)
3868 : : {
3869 : 37 : hook = emission_hooks[i];
3870 : :
3871 : 37 : g_hook_unref (node->emission_hooks, hook);
3872 : :
3873 : 37 : if (hook_returns[i])
3874 : 11 : g_hook_destroy_link (node->emission_hooks, hook);
3875 : : }
3876 : : }
3877 : :
3878 : 14 : if (emission.state == EMISSION_RESTART)
3879 : 0 : goto EMIT_RESTART;
3880 : : }
3881 : :
3882 : 8431459 : if (handler_list)
3883 : : {
3884 : 6450273 : Handler *handler = handler_list;
3885 : :
3886 : 6450273 : emission.state = EMISSION_RUN;
3887 : 6450273 : handler_ref (handler);
3888 : : do
3889 : : {
3890 : : Handler *tmp;
3891 : :
3892 : 6767772 : if (handler->after)
3893 : : {
3894 : 24 : handler_unref_R (signal_id, instance, handler_list);
3895 : 24 : handler_list = handler;
3896 : 24 : break;
3897 : : }
3898 : 6767748 : else if (!handler->block_count && (!handler->detail || handler->detail == detail) &&
3899 : 6451460 : handler->sequential_number < max_sequential_handler_number)
3900 : : {
3901 : 6451459 : SIGNAL_UNLOCK ();
3902 : 6451459 : return_accu = maybe_init_accumulator_unlocked (node, emission_return, &accu);
3903 : 6451459 : g_closure_invoke (handler->closure,
3904 : : return_accu,
3905 : : n_params,
3906 : : instance_and_params,
3907 : : &emission.ihint);
3908 : 6451453 : if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) &&
3909 : 345 : emission.state == EMISSION_RUN)
3910 : 345 : emission.state = EMISSION_STOP;
3911 : 6451453 : SIGNAL_LOCK ();
3912 : 6451453 : return_value_altered = TRUE;
3913 : :
3914 : 6451453 : tmp = emission.state == EMISSION_RUN ? handler->next : NULL;
3915 : : }
3916 : : else
3917 : 316289 : tmp = handler->next;
3918 : :
3919 : 6767742 : if (tmp)
3920 : 317499 : handler_ref (tmp);
3921 : 6767742 : handler_unref_R (signal_id, instance, handler_list);
3922 : 6767742 : handler_list = handler;
3923 : 6767742 : handler = tmp;
3924 : : }
3925 : 6767742 : while (handler);
3926 : :
3927 : 6450267 : if (emission.state == EMISSION_STOP)
3928 : 347 : goto EMIT_CLEANUP;
3929 : 6449920 : else if (emission.state == EMISSION_RESTART)
3930 : 42897 : goto EMIT_RESTART;
3931 : : }
3932 : :
3933 : 8388209 : emission.ihint.run_type &= (unsigned) ~G_SIGNAL_RUN_FIRST;
3934 : 8388209 : emission.ihint.run_type |= G_SIGNAL_RUN_LAST;
3935 : :
3936 : 8388209 : if ((node->flags & G_SIGNAL_RUN_LAST) && class_closure)
3937 : : {
3938 : 4241042 : emission.state = EMISSION_RUN;
3939 : :
3940 : 4241042 : emission.chain_type = G_TYPE_FROM_INSTANCE (instance);
3941 : 4241042 : SIGNAL_UNLOCK ();
3942 : 4241042 : return_accu = maybe_init_accumulator_unlocked (node, emission_return, &accu);
3943 : 4241042 : g_closure_invoke (class_closure,
3944 : : return_accu,
3945 : : n_params,
3946 : : instance_and_params,
3947 : : &emission.ihint);
3948 : 4241042 : if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) &&
3949 : 2 : emission.state == EMISSION_RUN)
3950 : 2 : emission.state = EMISSION_STOP;
3951 : 4241042 : SIGNAL_LOCK ();
3952 : 4241042 : emission.chain_type = G_TYPE_NONE;
3953 : 4241042 : return_value_altered = TRUE;
3954 : :
3955 : 4241042 : if (emission.state == EMISSION_STOP)
3956 : 2 : goto EMIT_CLEANUP;
3957 : 4241040 : else if (emission.state == EMISSION_RESTART)
3958 : 0 : goto EMIT_RESTART;
3959 : : }
3960 : :
3961 : 8388207 : if (handler_list)
3962 : : {
3963 : 6407022 : Handler *handler = handler_list;
3964 : :
3965 : 6407022 : emission.state = EMISSION_RUN;
3966 : 6407022 : handler_ref (handler);
3967 : : do
3968 : : {
3969 : : Handler *tmp;
3970 : :
3971 : 6407022 : if (handler->after && !handler->block_count && (!handler->detail || handler->detail == detail) &&
3972 : 23 : handler->sequential_number < max_sequential_handler_number)
3973 : : {
3974 : 23 : SIGNAL_UNLOCK ();
3975 : 23 : return_accu = maybe_init_accumulator_unlocked (node, emission_return, &accu);
3976 : 23 : g_closure_invoke (handler->closure,
3977 : : return_accu,
3978 : : n_params,
3979 : : instance_and_params,
3980 : : &emission.ihint);
3981 : 23 : if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) &&
3982 : 2 : emission.state == EMISSION_RUN)
3983 : 2 : emission.state = EMISSION_STOP;
3984 : 23 : SIGNAL_LOCK ();
3985 : 23 : return_value_altered = TRUE;
3986 : :
3987 : 23 : tmp = emission.state == EMISSION_RUN ? handler->next : NULL;
3988 : : }
3989 : : else
3990 : 6406999 : tmp = handler->next;
3991 : :
3992 : 6407022 : if (tmp)
3993 : 0 : handler_ref (tmp);
3994 : 6407022 : handler_unref_R (signal_id, instance, handler);
3995 : 6407022 : handler = tmp;
3996 : : }
3997 : 6407022 : while (handler);
3998 : :
3999 : 6407022 : if (emission.state == EMISSION_STOP)
4000 : 2 : goto EMIT_CLEANUP;
4001 : 6407020 : else if (emission.state == EMISSION_RESTART)
4002 : 0 : goto EMIT_RESTART;
4003 : : }
4004 : :
4005 : 8388205 : EMIT_CLEANUP:
4006 : :
4007 : 8388556 : emission.ihint.run_type &= (unsigned) ~G_SIGNAL_RUN_LAST;
4008 : 8388556 : emission.ihint.run_type |= G_SIGNAL_RUN_CLEANUP;
4009 : :
4010 : 8388556 : if ((node->flags & G_SIGNAL_RUN_CLEANUP) && class_closure)
4011 : : {
4012 : 4 : gboolean need_unset = FALSE;
4013 : :
4014 : 4 : emission.state = EMISSION_STOP;
4015 : :
4016 : 4 : emission.chain_type = G_TYPE_FROM_INSTANCE (instance);
4017 : 4 : SIGNAL_UNLOCK ();
4018 : 4 : if (node->return_type != G_TYPE_NONE && !accumulator)
4019 : : {
4020 : 0 : g_value_init (&accu, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
4021 : 0 : need_unset = TRUE;
4022 : : }
4023 : 4 : g_closure_invoke (class_closure,
4024 : 4 : node->return_type != G_TYPE_NONE ? &accu : NULL,
4025 : : n_params,
4026 : : instance_and_params,
4027 : : &emission.ihint);
4028 : 4 : if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) &&
4029 : 0 : emission.state == EMISSION_RUN)
4030 : 0 : emission.state = EMISSION_STOP;
4031 : 4 : if (need_unset)
4032 : 0 : g_value_unset (&accu);
4033 : 4 : SIGNAL_LOCK ();
4034 : 4 : return_value_altered = TRUE;
4035 : :
4036 : 4 : emission.chain_type = G_TYPE_NONE;
4037 : :
4038 : 4 : if (emission.state == EMISSION_RESTART)
4039 : 0 : goto EMIT_RESTART;
4040 : : }
4041 : :
4042 : 8388556 : if (handler_list)
4043 : 6407370 : handler_unref_R (signal_id, instance, handler_list);
4044 : :
4045 : 8388556 : emission_pop (&emission);
4046 : 8388556 : if (accumulator)
4047 : 901 : g_value_unset (&accu);
4048 : :
4049 : 8388556 : TRACE(GOBJECT_SIGNAL_EMIT_END(node->signal_id, detail, instance, G_TYPE_FROM_INSTANCE (instance)));
4050 : :
4051 : 8388556 : return return_value_altered;
4052 : : }
4053 : :
4054 : : static void
4055 : 10335 : add_invalid_closure_notify (Handler *handler,
4056 : : gpointer instance)
4057 : : {
4058 : 10335 : g_closure_add_invalidate_notifier (handler->closure, instance, invalid_closure_notify);
4059 : 10335 : handler->has_invalid_closure_notify = 1;
4060 : 10335 : }
4061 : :
4062 : : static void
4063 : 531805 : remove_invalid_closure_notify (Handler *handler,
4064 : : gpointer instance)
4065 : : {
4066 : 531805 : if (handler->has_invalid_closure_notify)
4067 : : {
4068 : 10274 : g_closure_remove_invalidate_notifier (handler->closure, instance, invalid_closure_notify);
4069 : 10274 : handler->has_invalid_closure_notify = 0;
4070 : : }
4071 : 531805 : }
4072 : :
4073 : : static void
4074 : 57 : invalid_closure_notify (gpointer instance,
4075 : : GClosure *closure)
4076 : : {
4077 : : Handler *handler;
4078 : : guint signal_id;
4079 : :
4080 : 57 : SIGNAL_LOCK ();
4081 : :
4082 : 57 : handler = handler_lookup (instance, 0, closure, &signal_id);
4083 : : /* See https://bugzilla.gnome.org/show_bug.cgi?id=730296 for discussion about this... */
4084 : 57 : g_assert (handler != NULL);
4085 : 57 : g_assert (handler->closure == closure);
4086 : :
4087 : 57 : g_hash_table_remove (g_handlers, handler);
4088 : 57 : handler->sequential_number = 0;
4089 : 57 : handler->block_count = 1;
4090 : 57 : handler_unref_R (signal_id, instance, handler);
4091 : :
4092 : 57 : SIGNAL_UNLOCK ();
4093 : 57 : }
4094 : :
4095 : : static const gchar*
4096 : 2 : type_debug_name (GType type)
4097 : : {
4098 : 2 : if (type)
4099 : : {
4100 : 2 : const char *name = g_type_name (type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
4101 : 2 : return name ? name : "<unknown>";
4102 : : }
4103 : : else
4104 : 0 : return "<invalid>";
4105 : : }
4106 : :
4107 : : /**
4108 : : * g_signal_accumulator_true_handled:
4109 : : * @ihint: standard #GSignalAccumulator parameter
4110 : : * @return_accu: standard #GSignalAccumulator parameter
4111 : : * @handler_return: standard #GSignalAccumulator parameter
4112 : : * @dummy: standard #GSignalAccumulator parameter
4113 : : *
4114 : : * A predefined #GSignalAccumulator for signals that return a
4115 : : * boolean values. The behavior that this accumulator gives is
4116 : : * that a return of %TRUE stops the signal emission: no further
4117 : : * callbacks will be invoked, while a return of %FALSE allows
4118 : : * the emission to continue. The idea here is that a %TRUE return
4119 : : * indicates that the callback handled the signal, and no further
4120 : : * handling is needed.
4121 : : *
4122 : : * Since: 2.4
4123 : : *
4124 : : * Returns: standard #GSignalAccumulator result
4125 : : */
4126 : : gboolean
4127 : 873 : g_signal_accumulator_true_handled (GSignalInvocationHint *ihint,
4128 : : GValue *return_accu,
4129 : : const GValue *handler_return,
4130 : : gpointer dummy)
4131 : : {
4132 : : gboolean continue_emission;
4133 : : gboolean signal_handled;
4134 : :
4135 : 873 : signal_handled = g_value_get_boolean (handler_return);
4136 : 873 : g_value_set_boolean (return_accu, signal_handled);
4137 : 873 : continue_emission = !signal_handled;
4138 : :
4139 : 873 : return continue_emission;
4140 : : }
4141 : :
4142 : : /**
4143 : : * g_signal_accumulator_first_wins:
4144 : : * @ihint: standard #GSignalAccumulator parameter
4145 : : * @return_accu: standard #GSignalAccumulator parameter
4146 : : * @handler_return: standard #GSignalAccumulator parameter
4147 : : * @dummy: standard #GSignalAccumulator parameter
4148 : : *
4149 : : * A predefined #GSignalAccumulator for signals intended to be used as a
4150 : : * hook for application code to provide a particular value. Usually
4151 : : * only one such value is desired and multiple handlers for the same
4152 : : * signal don't make much sense (except for the case of the default
4153 : : * handler defined in the class structure, in which case you will
4154 : : * usually want the signal connection to override the class handler).
4155 : : *
4156 : : * This accumulator will use the return value from the first signal
4157 : : * handler that is run as the return value for the signal and not run
4158 : : * any further handlers (ie: the first handler "wins").
4159 : : *
4160 : : * Returns: standard #GSignalAccumulator result
4161 : : *
4162 : : * Since: 2.28
4163 : : **/
4164 : : gboolean
4165 : 10 : g_signal_accumulator_first_wins (GSignalInvocationHint *ihint,
4166 : : GValue *return_accu,
4167 : : const GValue *handler_return,
4168 : : gpointer dummy)
4169 : : {
4170 : 10 : g_value_copy (handler_return, return_accu);
4171 : 10 : return FALSE;
4172 : : }
4173 : :
4174 : : /**
4175 : : * g_clear_signal_handler:
4176 : : * @handler_id_ptr: A pointer to a handler ID (of type #gulong) of the handler to be disconnected.
4177 : : * @instance: (type GObject.Object): The instance to remove the signal handler from.
4178 : : * This pointer may be %NULL or invalid, if the handler ID is zero.
4179 : : *
4180 : : * Disconnects a handler from @instance so it will not be called during
4181 : : * any future or currently ongoing emissions of the signal it has been
4182 : : * connected to. The @handler_id_ptr is then set to zero, which is never a valid handler ID value (see g_signal_connect()).
4183 : : *
4184 : : * If the handler ID is 0 then this function does nothing.
4185 : : *
4186 : : * There is also a macro version of this function so that the code
4187 : : * will be inlined.
4188 : : *
4189 : : * Since: 2.62
4190 : : */
4191 : : void
4192 : 0 : (g_clear_signal_handler) (gulong *handler_id_ptr,
4193 : : gpointer instance)
4194 : : {
4195 : 0 : g_return_if_fail (handler_id_ptr != NULL);
4196 : :
4197 : : #ifndef g_clear_signal_handler
4198 : : #error g_clear_signal_handler() macro is not defined
4199 : : #endif
4200 : :
4201 : 0 : g_clear_signal_handler (handler_id_ptr, instance);
4202 : : }
|