gsignal.c revision 0cba1b531d5d28890fa4f48359d4e7adacf2a603
1/* GObject - GLib Type, Object, Parameter and Signal Library 2 * Copyright (C) 2000-2001 Red Hat, Inc. 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General 15 * Public License along with this library; if not, write to the 16 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17 * Boston, MA 02111-1307, USA. 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 "gsignal.h" 30 31#include "gbsearcharray.h" 32#include "gvaluecollector.h" 33#include "gvaluetypes.h" 34#include "gboxed.h" 35 36#include "gobjectalias.h" 37 38#include <string.h> 39#include <signal.h> 40 41 42/* pre allocation configurations 43 */ 44#define MAX_STACK_VALUES (16) 45 46#define REPORT_BUG "please report occurrence circumstances to gtk-devel-list@gnome.org" 47#ifdef G_ENABLE_DEBUG 48#define IF_DEBUG(debug_type, cond) if ((_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type) || cond) 49static volatile gpointer g_trace_instance_signals = NULL; 50static volatile gpointer g_trap_instance_signals = NULL; 51#endif /* G_ENABLE_DEBUG */ 52 53 54/* --- typedefs --- */ 55typedef struct _SignalNode SignalNode; 56typedef struct _SignalKey SignalKey; 57typedef struct _Emission Emission; 58typedef struct _Handler Handler; 59typedef struct _HandlerList HandlerList; 60typedef struct _HandlerMatch HandlerMatch; 61typedef enum 62{ 63 EMISSION_STOP, 64 EMISSION_RUN, 65 EMISSION_HOOK, 66 EMISSION_RESTART 67} EmissionState; 68 69 70/* --- prototypes --- */ 71static inline guint signal_id_lookup (GQuark quark, 72 GType itype); 73static void signal_destroy_R (SignalNode *signal_node); 74static inline HandlerList* handler_list_ensure (guint signal_id, 75 gpointer instance); 76static inline HandlerList* handler_list_lookup (guint signal_id, 77 gpointer instance); 78static inline Handler* handler_new (gboolean after); 79static void handler_insert (guint signal_id, 80 gpointer instance, 81 Handler *handler); 82static Handler* handler_lookup (gpointer instance, 83 gulong handler_id, 84 guint *signal_id_p); 85static inline HandlerMatch* handler_match_prepend (HandlerMatch *list, 86 Handler *handler, 87 guint signal_id); 88static inline HandlerMatch* handler_match_free1_R (HandlerMatch *node, 89 gpointer instance); 90static HandlerMatch* handlers_find (gpointer instance, 91 GSignalMatchType mask, 92 guint signal_id, 93 GQuark detail, 94 GClosure *closure, 95 gpointer func, 96 gpointer data, 97 gboolean one_and_only); 98static inline void handler_ref (Handler *handler); 99static inline void handler_unref_R (guint signal_id, 100 gpointer instance, 101 Handler *handler); 102static gint handler_lists_cmp (gconstpointer node1, 103 gconstpointer node2); 104static inline void emission_push (Emission **emission_list_p, 105 Emission *emission); 106static inline void emission_pop (Emission **emission_list_p, 107 Emission *emission); 108static inline Emission* emission_find (Emission *emission_list, 109 guint signal_id, 110 GQuark detail, 111 gpointer instance); 112static gint class_closures_cmp (gconstpointer node1, 113 gconstpointer node2); 114static gint signal_key_cmp (gconstpointer node1, 115 gconstpointer node2); 116static gboolean signal_emit_unlocked_R (SignalNode *node, 117 GQuark detail, 118 gpointer instance, 119 GValue *return_value, 120 const GValue *instance_and_params); 121static const gchar * type_debug_name (GType type); 122 123 124/* --- structures --- */ 125typedef struct 126{ 127 GSignalAccumulator func; 128 gpointer data; 129} SignalAccumulator; 130typedef struct 131{ 132 GHook hook; 133 GQuark detail; 134} SignalHook; 135#define SIGNAL_HOOK(hook) ((SignalHook*) (hook)) 136 137struct _SignalNode 138{ 139 /* permanent portion */ 140 guint signal_id; 141 GType itype; 142 const gchar *name; 143 guint destroyed : 1; 144 145 /* reinitializable portion */ 146 guint test_class_offset : 12; 147 guint flags : 8; 148 guint n_params : 8; 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 GHookList *emission_hooks; 155}; 156#define MAX_TEST_CLASS_OFFSET (4096) /* 2^12, 12 bits for test_class_offset */ 157#define TEST_CLASS_MAGIC (1) /* indicates NULL class closure, candidate for NOP optimization */ 158 159struct _SignalKey 160{ 161 GType itype; 162 GQuark quark; 163 guint signal_id; 164}; 165 166struct _Emission 167{ 168 Emission *next; 169 gpointer instance; 170 GSignalInvocationHint ihint; 171 EmissionState state; 172 GType chain_type; 173}; 174 175struct _HandlerList 176{ 177 guint signal_id; 178 Handler *handlers; 179 Handler *tail_before; /* normal signal handlers are appended here */ 180 Handler *tail_after; /* CONNECT_AFTER handlers are appended here */ 181}; 182 183struct _Handler 184{ 185 gulong sequential_number; 186 Handler *next; 187 Handler *prev; 188 GQuark detail; 189 guint ref_count; 190 guint block_count : 16; 191#define HANDLER_MAX_BLOCK_COUNT (1 << 16) 192 guint after : 1; 193 GClosure *closure; 194}; 195struct _HandlerMatch 196{ 197 Handler *handler; 198 HandlerMatch *next; 199 guint signal_id; 200}; 201 202typedef struct 203{ 204 GType instance_type; /* 0 for default closure */ 205 GClosure *closure; 206} ClassClosure; 207 208 209/* --- variables --- */ 210static GBSearchArray *g_signal_key_bsa = NULL; 211static const GBSearchConfig g_signal_key_bconfig = { 212 sizeof (SignalKey), 213 signal_key_cmp, 214 G_BSEARCH_ARRAY_ALIGN_POWER2, 215}; 216static GBSearchConfig g_signal_hlbsa_bconfig = { 217 sizeof (HandlerList), 218 handler_lists_cmp, 219 0, 220}; 221static GBSearchConfig g_class_closure_bconfig = { 222 sizeof (ClassClosure), 223 class_closures_cmp, 224 0, 225}; 226static GHashTable *g_handler_list_bsa_ht = NULL; 227static Emission *g_recursive_emissions = NULL; 228static Emission *g_restart_emissions = NULL; 229#ifndef DISABLE_MEM_POOLS 230static GTrashStack *g_handler_ts = NULL; 231#endif 232static gulong g_handler_sequential_number = 1; 233G_LOCK_DEFINE_STATIC (g_signal_mutex); 234#define SIGNAL_LOCK() G_LOCK (g_signal_mutex) 235#define SIGNAL_UNLOCK() G_UNLOCK (g_signal_mutex) 236 237 238/* --- signal nodes --- */ 239static guint g_n_signal_nodes = 0; 240static SignalNode **g_signal_nodes = NULL; 241 242static inline SignalNode* 243LOOKUP_SIGNAL_NODE (register guint signal_id) 244{ 245 if (signal_id < g_n_signal_nodes) 246 return g_signal_nodes[signal_id]; 247 else 248 return NULL; 249} 250 251 252/* --- functions --- */ 253static inline guint 254signal_id_lookup (GQuark quark, 255 GType itype) 256{ 257 GType *ifaces, type = itype; 258 SignalKey key; 259 guint n_ifaces; 260 261 key.quark = quark; 262 263 /* try looking up signals for this type and its ancestors */ 264 do 265 { 266 SignalKey *signal_key; 267 268 key.itype = type; 269 signal_key = g_bsearch_array_lookup (g_signal_key_bsa, &g_signal_key_bconfig, &key); 270 271 if (signal_key) 272 return signal_key->signal_id; 273 274 type = g_type_parent (type); 275 } 276 while (type); 277 278 /* no luck, try interfaces it exports */ 279 ifaces = g_type_interfaces (itype, &n_ifaces); 280 while (n_ifaces--) 281 { 282 SignalKey *signal_key; 283 284 key.itype = ifaces[n_ifaces]; 285 signal_key = g_bsearch_array_lookup (g_signal_key_bsa, &g_signal_key_bconfig, &key); 286 287 if (signal_key) 288 { 289 g_free (ifaces); 290 return signal_key->signal_id; 291 } 292 } 293 g_free (ifaces); 294 295 return 0; 296} 297 298static gint 299class_closures_cmp (gconstpointer node1, 300 gconstpointer node2) 301{ 302 const ClassClosure *c1 = node1, *c2 = node2; 303 304 return G_BSEARCH_ARRAY_CMP (c1->instance_type, c2->instance_type); 305} 306 307static gint 308handler_lists_cmp (gconstpointer node1, 309 gconstpointer node2) 310{ 311 const HandlerList *hlist1 = node1, *hlist2 = node2; 312 313 return G_BSEARCH_ARRAY_CMP (hlist1->signal_id, hlist2->signal_id); 314} 315 316static inline HandlerList* 317handler_list_ensure (guint signal_id, 318 gpointer instance) 319{ 320 GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance); 321 HandlerList key; 322 323 key.signal_id = signal_id; 324 key.handlers = NULL; 325 key.tail_before = NULL; 326 key.tail_after = NULL; 327 if (!hlbsa) 328 { 329 hlbsa = g_bsearch_array_create (&g_signal_hlbsa_bconfig); 330 hlbsa = g_bsearch_array_insert (hlbsa, &g_signal_hlbsa_bconfig, &key); 331 g_hash_table_insert (g_handler_list_bsa_ht, instance, hlbsa); 332 } 333 else 334 { 335 GBSearchArray *o = hlbsa; 336 337 hlbsa = g_bsearch_array_insert (o, &g_signal_hlbsa_bconfig, &key); 338 if (hlbsa != o) 339 g_hash_table_insert (g_handler_list_bsa_ht, instance, hlbsa); 340 } 341 return g_bsearch_array_lookup (hlbsa, &g_signal_hlbsa_bconfig, &key); 342} 343 344static inline HandlerList* 345handler_list_lookup (guint signal_id, 346 gpointer instance) 347{ 348 GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance); 349 HandlerList key; 350 351 key.signal_id = signal_id; 352 353 return hlbsa ? g_bsearch_array_lookup (hlbsa, &g_signal_hlbsa_bconfig, &key) : NULL; 354} 355 356static Handler* 357handler_lookup (gpointer instance, 358 gulong handler_id, 359 guint *signal_id_p) 360{ 361 GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance); 362 363 if (hlbsa) 364 { 365 guint i; 366 367 for (i = 0; i < hlbsa->n_nodes; i++) 368 { 369 HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, &g_signal_hlbsa_bconfig, i); 370 Handler *handler; 371 372 for (handler = hlist->handlers; handler; handler = handler->next) 373 if (handler->sequential_number == handler_id) 374 { 375 if (signal_id_p) 376 *signal_id_p = hlist->signal_id; 377 378 return handler; 379 } 380 } 381 } 382 383 return NULL; 384} 385 386static inline HandlerMatch* 387handler_match_prepend (HandlerMatch *list, 388 Handler *handler, 389 guint signal_id) 390{ 391 HandlerMatch *node; 392 393 /* yeah, we could use our own memchunk here, introducing yet more 394 * rarely used cached nodes and extra allocation overhead. 395 * instead, we use GList* nodes, since they are exactly the size 396 * we need and are already cached. g_signal_init() asserts this. 397 */ 398 node = g_slice_new (HandlerMatch); 399 node->handler = handler; 400 node->next = list; 401 node->signal_id = signal_id; 402 handler_ref (handler); 403 404 return node; 405} 406static inline HandlerMatch* 407handler_match_free1_R (HandlerMatch *node, 408 gpointer instance) 409{ 410 HandlerMatch *next = node->next; 411 412 handler_unref_R (node->signal_id, instance, node->handler); 413 g_slice_free (HandlerMatch, node); 414 415 return next; 416} 417 418static HandlerMatch* 419handlers_find (gpointer instance, 420 GSignalMatchType mask, 421 guint signal_id, 422 GQuark detail, 423 GClosure *closure, 424 gpointer func, 425 gpointer data, 426 gboolean one_and_only) 427{ 428 HandlerMatch *mlist = NULL; 429 430 if (mask & G_SIGNAL_MATCH_ID) 431 { 432 HandlerList *hlist = handler_list_lookup (signal_id, instance); 433 Handler *handler; 434 SignalNode *node = NULL; 435 436 if (mask & G_SIGNAL_MATCH_FUNC) 437 { 438 node = LOOKUP_SIGNAL_NODE (signal_id); 439 if (!node || !node->c_marshaller) 440 return NULL; 441 } 442 443 mask = ~mask; 444 for (handler = hlist ? hlist->handlers : NULL; handler; handler = handler->next) 445 if (handler->sequential_number && 446 ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) && 447 ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) && 448 ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) && 449 ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) && 450 ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller && 451 handler->closure->meta_marshal == 0 && 452 ((GCClosure*) handler->closure)->callback == func))) 453 { 454 mlist = handler_match_prepend (mlist, handler, signal_id); 455 if (one_and_only) 456 return mlist; 457 } 458 } 459 else 460 { 461 GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance); 462 463 mask = ~mask; 464 if (hlbsa) 465 { 466 guint i; 467 468 for (i = 0; i < hlbsa->n_nodes; i++) 469 { 470 HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, &g_signal_hlbsa_bconfig, i); 471 SignalNode *node = NULL; 472 Handler *handler; 473 474 if (!(mask & G_SIGNAL_MATCH_FUNC)) 475 { 476 node = LOOKUP_SIGNAL_NODE (hlist->signal_id); 477 if (!node->c_marshaller) 478 continue; 479 } 480 481 for (handler = hlist->handlers; handler; handler = handler->next) 482 if (handler->sequential_number && 483 ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) && 484 ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) && 485 ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) && 486 ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) && 487 ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller && 488 handler->closure->meta_marshal == 0 && 489 ((GCClosure*) handler->closure)->callback == func))) 490 { 491 mlist = handler_match_prepend (mlist, handler, hlist->signal_id); 492 if (one_and_only) 493 return mlist; 494 } 495 } 496 } 497 } 498 499 return mlist; 500} 501 502static inline Handler* 503handler_new (gboolean after) 504{ 505 Handler *handler = g_slice_new (Handler); 506#ifndef G_DISABLE_CHECKS 507 if (g_handler_sequential_number < 1) 508 g_error (G_STRLOC ": handler id overflow, %s", REPORT_BUG); 509#endif 510 511 handler->sequential_number = g_handler_sequential_number++; 512 handler->prev = NULL; 513 handler->next = NULL; 514 handler->detail = 0; 515 handler->ref_count = 1; 516 handler->block_count = 0; 517 handler->after = after != FALSE; 518 handler->closure = NULL; 519 520 return handler; 521} 522 523static inline void 524handler_ref (Handler *handler) 525{ 526 g_return_if_fail (handler->ref_count > 0); 527 528 g_atomic_int_inc (&handler->ref_count); 529} 530 531static inline void 532handler_unref_R (guint signal_id, 533 gpointer instance, 534 Handler *handler) 535{ 536 gboolean is_zero; 537 538 g_return_if_fail (handler->ref_count > 0); 539 540 is_zero = g_atomic_int_dec_and_test (&handler->ref_count); 541 542 if (G_UNLIKELY (is_zero)) 543 { 544 HandlerList *hlist = NULL; 545 546 if (handler->next) 547 handler->next->prev = handler->prev; 548 if (handler->prev) /* watch out for g_signal_handlers_destroy()! */ 549 handler->prev->next = handler->next; 550 else 551 { 552 hlist = handler_list_lookup (signal_id, instance); 553 hlist->handlers = handler->next; 554 } 555 556 if (instance) 557 { 558 /* check if we are removing the handler pointed to by tail_before */ 559 if (!handler->after && (!handler->next || handler->next->after)) 560 { 561 if (!hlist) 562 hlist = handler_list_lookup (signal_id, instance); 563 if (hlist) 564 { 565 g_assert (hlist->tail_before == handler); /* paranoid */ 566 hlist->tail_before = handler->prev; 567 } 568 } 569 570 /* check if we are removing the handler pointed to by tail_after */ 571 if (!handler->next) 572 { 573 if (!hlist) 574 hlist = handler_list_lookup (signal_id, instance); 575 if (hlist) 576 { 577 g_assert (hlist->tail_after == handler); /* paranoid */ 578 hlist->tail_after = handler->prev; 579 } 580 } 581 } 582 583 SIGNAL_UNLOCK (); 584 g_closure_unref (handler->closure); 585 SIGNAL_LOCK (); 586 g_slice_free (Handler, handler); 587 } 588} 589 590static void 591handler_insert (guint signal_id, 592 gpointer instance, 593 Handler *handler) 594{ 595 HandlerList *hlist; 596 597 g_assert (handler->prev == NULL && handler->next == NULL); /* paranoid */ 598 599 hlist = handler_list_ensure (signal_id, instance); 600 if (!hlist->handlers) 601 { 602 hlist->handlers = handler; 603 if (!handler->after) 604 hlist->tail_before = handler; 605 } 606 else if (handler->after) 607 { 608 handler->prev = hlist->tail_after; 609 hlist->tail_after->next = handler; 610 } 611 else 612 { 613 if (hlist->tail_before) 614 { 615 handler->next = hlist->tail_before->next; 616 if (handler->next) 617 handler->next->prev = handler; 618 handler->prev = hlist->tail_before; 619 hlist->tail_before->next = handler; 620 } 621 else /* insert !after handler into a list of only after handlers */ 622 { 623 handler->next = hlist->handlers; 624 if (handler->next) 625 handler->next->prev = handler; 626 hlist->handlers = handler; 627 } 628 hlist->tail_before = handler; 629 } 630 631 if (!handler->next) 632 hlist->tail_after = handler; 633} 634 635static inline void 636emission_push (Emission **emission_list_p, 637 Emission *emission) 638{ 639 emission->next = *emission_list_p; 640 *emission_list_p = emission; 641} 642 643static inline void 644emission_pop (Emission **emission_list_p, 645 Emission *emission) 646{ 647 Emission *node, *last = NULL; 648 649 for (node = *emission_list_p; node; last = node, node = last->next) 650 if (node == emission) 651 { 652 if (last) 653 last->next = node->next; 654 else 655 *emission_list_p = node->next; 656 return; 657 } 658 g_assert_not_reached (); 659} 660 661static inline Emission* 662emission_find (Emission *emission_list, 663 guint signal_id, 664 GQuark detail, 665 gpointer instance) 666{ 667 Emission *emission; 668 669 for (emission = emission_list; emission; emission = emission->next) 670 if (emission->instance == instance && 671 emission->ihint.signal_id == signal_id && 672 emission->ihint.detail == detail) 673 return emission; 674 return NULL; 675} 676 677static inline Emission* 678emission_find_innermost (gpointer instance) 679{ 680 Emission *emission, *s = NULL, *c = NULL; 681 682 for (emission = g_restart_emissions; emission; emission = emission->next) 683 if (emission->instance == instance) 684 { 685 s = emission; 686 break; 687 } 688 for (emission = g_recursive_emissions; emission; emission = emission->next) 689 if (emission->instance == instance) 690 { 691 c = emission; 692 break; 693 } 694 if (!s) 695 return c; 696 else if (!c) 697 return s; 698 else 699 return G_HAVE_GROWING_STACK ? MAX (c, s) : MIN (c, s); 700} 701 702static gint 703signal_key_cmp (gconstpointer node1, 704 gconstpointer node2) 705{ 706 const SignalKey *key1 = node1, *key2 = node2; 707 708 if (key1->itype == key2->itype) 709 return G_BSEARCH_ARRAY_CMP (key1->quark, key2->quark); 710 else 711 return G_BSEARCH_ARRAY_CMP (key1->itype, key2->itype); 712} 713 714void 715g_signal_init (void) 716{ 717 SIGNAL_LOCK (); 718 if (!g_n_signal_nodes) 719 { 720 /* handler_id_node_prepend() requires this */ 721 g_assert (sizeof (GList) == sizeof (HandlerMatch)); 722 723 /* setup handler list binary searchable array hash table (in german, that'd be one word ;) */ 724 g_handler_list_bsa_ht = g_hash_table_new (g_direct_hash, NULL); 725 g_signal_key_bsa = g_bsearch_array_create (&g_signal_key_bconfig); 726 727 /* invalid (0) signal_id */ 728 g_n_signal_nodes = 1; 729 g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes); 730 g_signal_nodes[0] = NULL; 731 } 732 SIGNAL_UNLOCK (); 733} 734 735void 736_g_signals_destroy (GType itype) 737{ 738 guint i; 739 740 SIGNAL_LOCK (); 741 for (i = 1; i < g_n_signal_nodes; i++) 742 { 743 SignalNode *node = g_signal_nodes[i]; 744 745 if (node->itype == itype) 746 { 747 if (node->destroyed) 748 g_warning (G_STRLOC ": signal \"%s\" of type `%s' already destroyed", 749 node->name, 750 type_debug_name (node->itype)); 751 else 752 signal_destroy_R (node); 753 } 754 } 755 SIGNAL_UNLOCK (); 756} 757 758void 759g_signal_stop_emission (gpointer instance, 760 guint signal_id, 761 GQuark detail) 762{ 763 SignalNode *node; 764 765 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 766 g_return_if_fail (signal_id > 0); 767 768 SIGNAL_LOCK (); 769 node = LOOKUP_SIGNAL_NODE (signal_id); 770 if (node && detail && !(node->flags & G_SIGNAL_DETAILED)) 771 { 772 g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); 773 SIGNAL_UNLOCK (); 774 return; 775 } 776 if (node && g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype)) 777 { 778 Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions; 779 Emission *emission = emission_find (emission_list, signal_id, detail, instance); 780 781 if (emission) 782 { 783 if (emission->state == EMISSION_HOOK) 784 g_warning (G_STRLOC ": emission of signal \"%s\" for instance `%p' cannot be stopped from emission hook", 785 node->name, instance); 786 else if (emission->state == EMISSION_RUN) 787 emission->state = EMISSION_STOP; 788 } 789 else 790 g_warning (G_STRLOC ": no emission of signal \"%s\" to stop for instance `%p'", 791 node->name, instance); 792 } 793 else 794 g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance); 795 SIGNAL_UNLOCK (); 796} 797 798static void 799signal_finalize_hook (GHookList *hook_list, 800 GHook *hook) 801{ 802 GDestroyNotify destroy = hook->destroy; 803 804 if (destroy) 805 { 806 hook->destroy = NULL; 807 SIGNAL_UNLOCK (); 808 destroy (hook->data); 809 SIGNAL_LOCK (); 810 } 811} 812 813gulong 814g_signal_add_emission_hook (guint signal_id, 815 GQuark detail, 816 GSignalEmissionHook hook_func, 817 gpointer hook_data, 818 GDestroyNotify data_destroy) 819{ 820 static gulong seq_hook_id = 1; 821 SignalNode *node; 822 GHook *hook; 823 SignalHook *signal_hook; 824 825 g_return_val_if_fail (signal_id > 0, 0); 826 g_return_val_if_fail (hook_func != NULL, 0); 827 828 SIGNAL_LOCK (); 829 node = LOOKUP_SIGNAL_NODE (signal_id); 830 if (!node || node->destroyed) 831 { 832 g_warning ("%s: invalid signal id `%u'", G_STRLOC, signal_id); 833 SIGNAL_UNLOCK (); 834 return 0; 835 } 836 if (node->flags & G_SIGNAL_NO_HOOKS) 837 { 838 g_warning ("%s: signal id `%u' does not support emission hooks (G_SIGNAL_NO_HOOKS flag set)", G_STRLOC, signal_id); 839 SIGNAL_UNLOCK (); 840 return 0; 841 } 842 if (detail && !(node->flags & G_SIGNAL_DETAILED)) 843 { 844 g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); 845 SIGNAL_UNLOCK (); 846 return 0; 847 } 848 if (!node->emission_hooks) 849 { 850 node->emission_hooks = g_new (GHookList, 1); 851 g_hook_list_init (node->emission_hooks, sizeof (SignalHook)); 852 node->emission_hooks->finalize_hook = signal_finalize_hook; 853 } 854 hook = g_hook_alloc (node->emission_hooks); 855 hook->data = hook_data; 856 hook->func = (gpointer) hook_func; 857 hook->destroy = data_destroy; 858 signal_hook = SIGNAL_HOOK (hook); 859 signal_hook->detail = detail; 860 node->emission_hooks->seq_id = seq_hook_id; 861 g_hook_append (node->emission_hooks, hook); 862 seq_hook_id = node->emission_hooks->seq_id; 863 SIGNAL_UNLOCK (); 864 865 return hook->hook_id; 866} 867 868void 869g_signal_remove_emission_hook (guint signal_id, 870 gulong hook_id) 871{ 872 SignalNode *node; 873 874 g_return_if_fail (signal_id > 0); 875 g_return_if_fail (hook_id > 0); 876 877 SIGNAL_LOCK (); 878 node = LOOKUP_SIGNAL_NODE (signal_id); 879 if (!node || node->destroyed) 880 g_warning ("%s: invalid signal id `%u'", G_STRLOC, signal_id); 881 else if (!node->emission_hooks || !g_hook_destroy (node->emission_hooks, hook_id)) 882 g_warning ("%s: signal \"%s\" had no hook (%lu) to remove", G_STRLOC, node->name, hook_id); 883 SIGNAL_UNLOCK (); 884} 885 886static inline guint 887signal_parse_name (const gchar *name, 888 GType itype, 889 GQuark *detail_p, 890 gboolean force_quark) 891{ 892 const gchar *colon = strchr (name, ':'); 893 guint signal_id; 894 895 if (!colon) 896 { 897 signal_id = signal_id_lookup (g_quark_try_string (name), itype); 898 if (signal_id && detail_p) 899 *detail_p = 0; 900 } 901 else if (colon[1] == ':') 902 { 903 gchar buffer[32]; 904 guint l = colon - name; 905 906 if (l < 32) 907 { 908 memcpy (buffer, name, l); 909 buffer[l] = 0; 910 signal_id = signal_id_lookup (g_quark_try_string (buffer), itype); 911 } 912 else 913 { 914 gchar *signal = g_new (gchar, l + 1); 915 916 memcpy (signal, name, l); 917 signal[l] = 0; 918 signal_id = signal_id_lookup (g_quark_try_string (signal), itype); 919 g_free (signal); 920 } 921 922 if (signal_id && detail_p) 923 *detail_p = colon[2] ? (force_quark ? g_quark_from_string : g_quark_try_string) (colon + 2) : 0; 924 } 925 else 926 signal_id = 0; 927 return signal_id; 928} 929 930gboolean 931g_signal_parse_name (const gchar *detailed_signal, 932 GType itype, 933 guint *signal_id_p, 934 GQuark *detail_p, 935 gboolean force_detail_quark) 936{ 937 SignalNode *node; 938 GQuark detail = 0; 939 guint signal_id; 940 941 g_return_val_if_fail (detailed_signal != NULL, FALSE); 942 g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), FALSE); 943 944 SIGNAL_LOCK (); 945 signal_id = signal_parse_name (detailed_signal, itype, &detail, force_detail_quark); 946 SIGNAL_UNLOCK (); 947 948 node = signal_id ? LOOKUP_SIGNAL_NODE (signal_id) : NULL; 949 if (!node || node->destroyed || 950 (detail && !(node->flags & G_SIGNAL_DETAILED))) 951 return FALSE; 952 953 if (signal_id_p) 954 *signal_id_p = signal_id; 955 if (detail_p) 956 *detail_p = detail; 957 958 return TRUE; 959} 960 961void 962g_signal_stop_emission_by_name (gpointer instance, 963 const gchar *detailed_signal) 964{ 965 guint signal_id; 966 GQuark detail = 0; 967 GType itype; 968 969 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 970 g_return_if_fail (detailed_signal != NULL); 971 972 SIGNAL_LOCK (); 973 itype = G_TYPE_FROM_INSTANCE (instance); 974 signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE); 975 if (signal_id) 976 { 977 SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id); 978 979 if (detail && !(node->flags & G_SIGNAL_DETAILED)) 980 g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal); 981 else if (!g_type_is_a (itype, node->itype)) 982 g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); 983 else 984 { 985 Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions; 986 Emission *emission = emission_find (emission_list, signal_id, detail, instance); 987 988 if (emission) 989 { 990 if (emission->state == EMISSION_HOOK) 991 g_warning (G_STRLOC ": emission of signal \"%s\" for instance `%p' cannot be stopped from emission hook", 992 node->name, instance); 993 else if (emission->state == EMISSION_RUN) 994 emission->state = EMISSION_STOP; 995 } 996 else 997 g_warning (G_STRLOC ": no emission of signal \"%s\" to stop for instance `%p'", 998 node->name, instance); 999 } 1000 } 1001 else 1002 g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); 1003 SIGNAL_UNLOCK (); 1004} 1005 1006guint 1007g_signal_lookup (const gchar *name, 1008 GType itype) 1009{ 1010 guint signal_id; 1011 g_return_val_if_fail (name != NULL, 0); 1012 g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0); 1013 1014 SIGNAL_LOCK (); 1015 signal_id = signal_id_lookup (g_quark_try_string (name), itype); 1016 SIGNAL_UNLOCK (); 1017 if (!signal_id) 1018 { 1019 /* give elaborate warnings */ 1020 if (!g_type_name (itype)) 1021 g_warning (G_STRLOC ": unable to lookup signal \"%s\" for invalid type id `%lu'", 1022 name, itype); 1023 else if (!G_TYPE_IS_INSTANTIATABLE (itype)) 1024 g_warning (G_STRLOC ": unable to lookup signal \"%s\" for non instantiatable type `%s'", 1025 name, g_type_name (itype)); 1026 else if (!g_type_class_peek (itype)) 1027 g_warning (G_STRLOC ": unable to lookup signal \"%s\" of unloaded type `%s'", 1028 name, g_type_name (itype)); 1029 } 1030 1031 return signal_id; 1032} 1033 1034guint* 1035g_signal_list_ids (GType itype, 1036 guint *n_ids) 1037{ 1038 SignalKey *keys; 1039 GArray *result; 1040 guint n_nodes; 1041 guint i; 1042 1043 g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), NULL); 1044 g_return_val_if_fail (n_ids != NULL, NULL); 1045 1046 SIGNAL_LOCK (); 1047 keys = g_bsearch_array_get_nth (g_signal_key_bsa, &g_signal_key_bconfig, 0); 1048 n_nodes = g_bsearch_array_get_n_nodes (g_signal_key_bsa); 1049 result = g_array_new (FALSE, FALSE, sizeof (guint)); 1050 1051 for (i = 0; i < n_nodes; i++) 1052 if (keys[i].itype == itype) 1053 { 1054 const gchar *name = g_quark_to_string (keys[i].quark); 1055 1056 /* Signal names with "_" in them are aliases to the same 1057 * name with "-" instead of "_". 1058 */ 1059 if (!strchr (name, '_')) 1060 g_array_append_val (result, keys[i].signal_id); 1061 } 1062 *n_ids = result->len; 1063 SIGNAL_UNLOCK (); 1064 if (!n_nodes) 1065 { 1066 /* give elaborate warnings */ 1067 if (!g_type_name (itype)) 1068 g_warning (G_STRLOC ": unable to list signals for invalid type id `%lu'", 1069 itype); 1070 else if (!G_TYPE_IS_INSTANTIATABLE (itype)) 1071 g_warning (G_STRLOC ": unable to list signals of non instantiatable type `%s'", 1072 g_type_name (itype)); 1073 else if (!g_type_class_peek (itype)) 1074 g_warning (G_STRLOC ": unable to list signals of unloaded type `%s'", 1075 g_type_name (itype)); 1076 } 1077 1078 return (guint*) g_array_free (result, FALSE); 1079} 1080 1081G_CONST_RETURN gchar* 1082g_signal_name (guint signal_id) 1083{ 1084 SignalNode *node; 1085 const gchar *name; 1086 1087 SIGNAL_LOCK (); 1088 node = LOOKUP_SIGNAL_NODE (signal_id); 1089 name = node ? node->name : NULL; 1090 SIGNAL_UNLOCK (); 1091 1092 return (char*) name; 1093} 1094 1095void 1096g_signal_query (guint signal_id, 1097 GSignalQuery *query) 1098{ 1099 SignalNode *node; 1100 1101 g_return_if_fail (query != NULL); 1102 1103 SIGNAL_LOCK (); 1104 node = LOOKUP_SIGNAL_NODE (signal_id); 1105 if (!node || node->destroyed) 1106 query->signal_id = 0; 1107 else 1108 { 1109 query->signal_id = node->signal_id; 1110 query->signal_name = node->name; 1111 query->itype = node->itype; 1112 query->signal_flags = node->flags; 1113 query->return_type = node->return_type; 1114 query->n_params = node->n_params; 1115 query->param_types = node->param_types; 1116 } 1117 SIGNAL_UNLOCK (); 1118} 1119 1120guint 1121g_signal_new (const gchar *signal_name, 1122 GType itype, 1123 GSignalFlags signal_flags, 1124 guint class_offset, 1125 GSignalAccumulator accumulator, 1126 gpointer accu_data, 1127 GSignalCMarshaller c_marshaller, 1128 GType return_type, 1129 guint n_params, 1130 ...) 1131{ 1132 va_list args; 1133 guint signal_id; 1134 1135 g_return_val_if_fail (signal_name != NULL, 0); 1136 1137 va_start (args, n_params); 1138 1139 signal_id = g_signal_new_valist (signal_name, itype, signal_flags, 1140 class_offset ? g_signal_type_cclosure_new (itype, class_offset) : NULL, 1141 accumulator, accu_data, c_marshaller, 1142 return_type, n_params, args); 1143 1144 va_end (args); 1145 1146 /* optimize NOP emissions with NULL class handlers */ 1147 if (signal_id && G_TYPE_IS_INSTANTIATABLE (itype) && return_type == G_TYPE_NONE && 1148 class_offset && class_offset < MAX_TEST_CLASS_OFFSET) 1149 { 1150 SignalNode *node; 1151 1152 SIGNAL_LOCK (); 1153 node = LOOKUP_SIGNAL_NODE (signal_id); 1154 node->test_class_offset = class_offset; 1155 SIGNAL_UNLOCK (); 1156 } 1157 1158 return signal_id; 1159} 1160 1161static inline ClassClosure* 1162signal_find_class_closure (SignalNode *node, 1163 GType itype) 1164{ 1165 GBSearchArray *bsa = node->class_closure_bsa; 1166 ClassClosure *cc; 1167 1168 if (bsa) 1169 { 1170 ClassClosure key; 1171 1172 /* cc->instance_type is 0 for default closure */ 1173 1174 key.instance_type = itype; 1175 cc = g_bsearch_array_lookup (bsa, &g_class_closure_bconfig, &key); 1176 while (!cc && key.instance_type) 1177 { 1178 key.instance_type = g_type_parent (key.instance_type); 1179 cc = g_bsearch_array_lookup (bsa, &g_class_closure_bconfig, &key); 1180 } 1181 } 1182 else 1183 cc = NULL; 1184 return cc; 1185} 1186 1187static inline GClosure* 1188signal_lookup_closure (SignalNode *node, 1189 GTypeInstance *instance) 1190{ 1191 ClassClosure *cc; 1192 1193 if (node->class_closure_bsa && g_bsearch_array_get_n_nodes (node->class_closure_bsa) == 1) 1194 cc = g_bsearch_array_get_nth (node->class_closure_bsa, &g_class_closure_bconfig, 0); 1195 else 1196 cc = signal_find_class_closure (node, G_TYPE_FROM_INSTANCE (instance)); 1197 return cc ? cc->closure : NULL; 1198} 1199 1200static void 1201signal_add_class_closure (SignalNode *node, 1202 GType itype, 1203 GClosure *closure) 1204{ 1205 ClassClosure key; 1206 1207 /* can't optimize NOP emissions with overridden class closures */ 1208 node->test_class_offset = 0; 1209 1210 if (!node->class_closure_bsa) 1211 node->class_closure_bsa = g_bsearch_array_create (&g_class_closure_bconfig); 1212 key.instance_type = itype; 1213 key.closure = g_closure_ref (closure); 1214 node->class_closure_bsa = g_bsearch_array_insert (node->class_closure_bsa, 1215 &g_class_closure_bconfig, 1216 &key); 1217 g_closure_sink (closure); 1218 if (node->c_marshaller && closure && G_CLOSURE_NEEDS_MARSHAL (closure)) 1219 g_closure_set_marshal (closure, node->c_marshaller); 1220} 1221 1222guint 1223g_signal_newv (const gchar *signal_name, 1224 GType itype, 1225 GSignalFlags signal_flags, 1226 GClosure *class_closure, 1227 GSignalAccumulator accumulator, 1228 gpointer accu_data, 1229 GSignalCMarshaller c_marshaller, 1230 GType return_type, 1231 guint n_params, 1232 GType *param_types) 1233{ 1234 gchar *name; 1235 guint signal_id, i; 1236 SignalNode *node; 1237 1238 g_return_val_if_fail (signal_name != NULL, 0); 1239 g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0); 1240 if (n_params) 1241 g_return_val_if_fail (param_types != NULL, 0); 1242 g_return_val_if_fail ((return_type & G_SIGNAL_TYPE_STATIC_SCOPE) == 0, 0); 1243 if (return_type == (G_TYPE_NONE & ~G_SIGNAL_TYPE_STATIC_SCOPE)) 1244 g_return_val_if_fail (accumulator == NULL, 0); 1245 if (!accumulator) 1246 g_return_val_if_fail (accu_data == NULL, 0); 1247 1248 name = g_strdup (signal_name); 1249 g_strdelimit (name, G_STR_DELIMITERS ":^", '_'); /* FIXME do character checks like for types */ 1250 1251 SIGNAL_LOCK (); 1252 1253 signal_id = signal_id_lookup (g_quark_try_string (name), itype); 1254 node = LOOKUP_SIGNAL_NODE (signal_id); 1255 if (node && !node->destroyed) 1256 { 1257 g_warning (G_STRLOC ": signal \"%s\" already exists in the `%s' %s", 1258 name, 1259 type_debug_name (node->itype), 1260 G_TYPE_IS_INTERFACE (node->itype) ? "interface" : "class ancestry"); 1261 g_free (name); 1262 SIGNAL_UNLOCK (); 1263 return 0; 1264 } 1265 if (node && node->itype != itype) 1266 { 1267 g_warning (G_STRLOC ": signal \"%s\" for type `%s' was previously created for type `%s'", 1268 name, 1269 type_debug_name (itype), 1270 type_debug_name (node->itype)); 1271 g_free (name); 1272 SIGNAL_UNLOCK (); 1273 return 0; 1274 } 1275 for (i = 0; i < n_params; i++) 1276 if (!G_TYPE_IS_VALUE (param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE)) 1277 { 1278 g_warning (G_STRLOC ": parameter %d of type `%s' for signal \"%s::%s\" is not a value type", 1279 i + 1, type_debug_name (param_types[i]), type_debug_name (itype), name); 1280 g_free (name); 1281 SIGNAL_UNLOCK (); 1282 return 0; 1283 } 1284 if (return_type != G_TYPE_NONE && !G_TYPE_IS_VALUE (return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE)) 1285 { 1286 g_warning (G_STRLOC ": return value of type `%s' for signal \"%s::%s\" is not a value type", 1287 type_debug_name (return_type), type_debug_name (itype), name); 1288 g_free (name); 1289 SIGNAL_UNLOCK (); 1290 return 0; 1291 } 1292 if (return_type != G_TYPE_NONE && 1293 (signal_flags & (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST | G_SIGNAL_RUN_CLEANUP)) == G_SIGNAL_RUN_FIRST) 1294 { 1295 g_warning (G_STRLOC ": signal \"%s::%s\" has return type `%s' and is only G_SIGNAL_RUN_FIRST", 1296 type_debug_name (itype), name, type_debug_name (return_type)); 1297 g_free (name); 1298 SIGNAL_UNLOCK (); 1299 return 0; 1300 } 1301 1302 /* setup permanent portion of signal node */ 1303 if (!node) 1304 { 1305 SignalKey key; 1306 1307 signal_id = g_n_signal_nodes++; 1308 node = g_new (SignalNode, 1); 1309 node->signal_id = signal_id; 1310 g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes); 1311 g_signal_nodes[signal_id] = node; 1312 node->itype = itype; 1313 node->name = name; 1314 key.itype = itype; 1315 key.quark = g_quark_from_string (node->name); 1316 key.signal_id = signal_id; 1317 g_signal_key_bsa = g_bsearch_array_insert (g_signal_key_bsa, &g_signal_key_bconfig, &key); 1318 g_strdelimit (name, "_", '-'); 1319 node->name = g_intern_string (name); 1320 key.quark = g_quark_from_string (name); 1321 g_signal_key_bsa = g_bsearch_array_insert (g_signal_key_bsa, &g_signal_key_bconfig, &key); 1322 } 1323 node->destroyed = FALSE; 1324 node->test_class_offset = 0; 1325 1326 /* setup reinitializable portion */ 1327 node->flags = signal_flags & G_SIGNAL_FLAGS_MASK; 1328 node->n_params = n_params; 1329 node->param_types = g_memdup (param_types, sizeof (GType) * n_params); 1330 node->return_type = return_type; 1331 node->class_closure_bsa = NULL; 1332 if (accumulator) 1333 { 1334 node->accumulator = g_new (SignalAccumulator, 1); 1335 node->accumulator->func = accumulator; 1336 node->accumulator->data = accu_data; 1337 } 1338 else 1339 node->accumulator = NULL; 1340 node->c_marshaller = c_marshaller; 1341 node->emission_hooks = NULL; 1342 if (class_closure) 1343 signal_add_class_closure (node, 0, class_closure); 1344 else if (G_TYPE_IS_INSTANTIATABLE (itype) && return_type == G_TYPE_NONE) 1345 { 1346 /* optimize NOP emissions */ 1347 node->test_class_offset = TEST_CLASS_MAGIC; 1348 } 1349 SIGNAL_UNLOCK (); 1350 1351 g_free (name); 1352 1353 return signal_id; 1354} 1355 1356guint 1357g_signal_new_valist (const gchar *signal_name, 1358 GType itype, 1359 GSignalFlags signal_flags, 1360 GClosure *class_closure, 1361 GSignalAccumulator accumulator, 1362 gpointer accu_data, 1363 GSignalCMarshaller c_marshaller, 1364 GType return_type, 1365 guint n_params, 1366 va_list args) 1367{ 1368 GType *param_types; 1369 guint i; 1370 guint signal_id; 1371 1372 if (n_params > 0) 1373 { 1374 param_types = g_new (GType, n_params); 1375 1376 for (i = 0; i < n_params; i++) 1377 param_types[i] = va_arg (args, GType); 1378 } 1379 else 1380 param_types = NULL; 1381 1382 signal_id = g_signal_newv (signal_name, itype, signal_flags, 1383 class_closure, accumulator, accu_data, c_marshaller, 1384 return_type, n_params, param_types); 1385 g_free (param_types); 1386 1387 return signal_id; 1388} 1389 1390static void 1391signal_destroy_R (SignalNode *signal_node) 1392{ 1393 SignalNode node = *signal_node; 1394 1395 signal_node->destroyed = TRUE; 1396 1397 /* reentrancy caution, zero out real contents first */ 1398 signal_node->test_class_offset = 0; 1399 signal_node->n_params = 0; 1400 signal_node->param_types = NULL; 1401 signal_node->return_type = 0; 1402 signal_node->class_closure_bsa = NULL; 1403 signal_node->accumulator = NULL; 1404 signal_node->c_marshaller = NULL; 1405 signal_node->emission_hooks = NULL; 1406 1407#ifdef G_ENABLE_DEBUG 1408 /* check current emissions */ 1409 { 1410 Emission *emission; 1411 1412 for (emission = (node.flags & G_SIGNAL_NO_RECURSE) ? g_restart_emissions : g_recursive_emissions; 1413 emission; emission = emission->next) 1414 if (emission->ihint.signal_id == node.signal_id) 1415 g_critical (G_STRLOC ": signal \"%s\" being destroyed is currently in emission (instance `%p')", 1416 node.name, emission->instance); 1417 } 1418#endif 1419 1420 /* free contents that need to 1421 */ 1422 SIGNAL_UNLOCK (); 1423 g_free (node.param_types); 1424 if (node.class_closure_bsa) 1425 { 1426 guint i; 1427 1428 for (i = 0; i < node.class_closure_bsa->n_nodes; i++) 1429 { 1430 ClassClosure *cc = g_bsearch_array_get_nth (node.class_closure_bsa, &g_class_closure_bconfig, i); 1431 1432 g_closure_unref (cc->closure); 1433 } 1434 g_bsearch_array_free (node.class_closure_bsa, &g_class_closure_bconfig); 1435 } 1436 g_free (node.accumulator); 1437 if (node.emission_hooks) 1438 { 1439 g_hook_list_clear (node.emission_hooks); 1440 g_free (node.emission_hooks); 1441 } 1442 SIGNAL_LOCK (); 1443} 1444 1445void 1446g_signal_override_class_closure (guint signal_id, 1447 GType instance_type, 1448 GClosure *class_closure) 1449{ 1450 SignalNode *node; 1451 1452 g_return_if_fail (signal_id > 0); 1453 g_return_if_fail (class_closure != NULL); 1454 1455 SIGNAL_LOCK (); 1456 node = LOOKUP_SIGNAL_NODE (signal_id); 1457 if (!g_type_is_a (instance_type, node->itype)) 1458 g_warning ("%s: type `%s' cannot be overridden for signal id `%u'", G_STRLOC, type_debug_name (instance_type), signal_id); 1459 else 1460 { 1461 ClassClosure *cc = signal_find_class_closure (node, instance_type); 1462 1463 if (cc && cc->instance_type == instance_type) 1464 g_warning ("%s: type `%s' is already overridden for signal id `%u'", G_STRLOC, type_debug_name (instance_type), signal_id); 1465 else 1466 signal_add_class_closure (node, instance_type, class_closure); 1467 } 1468 SIGNAL_UNLOCK (); 1469} 1470 1471void 1472g_signal_chain_from_overridden (const GValue *instance_and_params, 1473 GValue *return_value) 1474{ 1475 GType chain_type = 0, restore_type = 0; 1476 Emission *emission = NULL; 1477 GClosure *closure = NULL; 1478 guint n_params = 0; 1479 gpointer instance; 1480 1481 g_return_if_fail (instance_and_params != NULL); 1482 instance = g_value_peek_pointer (instance_and_params); 1483 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 1484 1485 SIGNAL_LOCK (); 1486 emission = emission_find_innermost (instance); 1487 if (emission) 1488 { 1489 SignalNode *node = LOOKUP_SIGNAL_NODE (emission->ihint.signal_id); 1490 1491 g_assert (node != NULL); /* paranoid */ 1492 1493 /* we should probably do the same parameter checks as g_signal_emit() here. 1494 */ 1495 if (emission->chain_type != G_TYPE_NONE) 1496 { 1497 ClassClosure *cc = signal_find_class_closure (node, emission->chain_type); 1498 1499 g_assert (cc != NULL); /* closure currently in call stack */ 1500 1501 n_params = node->n_params; 1502 restore_type = cc->instance_type; 1503 cc = signal_find_class_closure (node, g_type_parent (cc->instance_type)); 1504 if (cc && cc->instance_type != restore_type) 1505 { 1506 closure = cc->closure; 1507 chain_type = cc->instance_type; 1508 } 1509 } 1510 else 1511 g_warning ("%s: signal id `%u' cannot be chained from current emission stage for instance `%p'", G_STRLOC, node->signal_id, instance); 1512 } 1513 else 1514 g_warning ("%s: no signal is currently being emitted for instance `%p'", G_STRLOC, instance); 1515 if (closure) 1516 { 1517 emission->chain_type = chain_type; 1518 SIGNAL_UNLOCK (); 1519 g_closure_invoke (closure, 1520 return_value, 1521 n_params + 1, 1522 instance_and_params, 1523 &emission->ihint); 1524 SIGNAL_LOCK (); 1525 emission->chain_type = restore_type; 1526 } 1527 SIGNAL_UNLOCK (); 1528} 1529 1530GSignalInvocationHint* 1531g_signal_get_invocation_hint (gpointer instance) 1532{ 1533 Emission *emission = NULL; 1534 1535 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), NULL); 1536 1537 SIGNAL_LOCK (); 1538 emission = emission_find_innermost (instance); 1539 SIGNAL_UNLOCK (); 1540 1541 return emission ? &emission->ihint : NULL; 1542} 1543 1544gulong 1545g_signal_connect_closure_by_id (gpointer instance, 1546 guint signal_id, 1547 GQuark detail, 1548 GClosure *closure, 1549 gboolean after) 1550{ 1551 SignalNode *node; 1552 gulong handler_seq_no = 0; 1553 1554 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); 1555 g_return_val_if_fail (signal_id > 0, 0); 1556 g_return_val_if_fail (closure != NULL, 0); 1557 1558 SIGNAL_LOCK (); 1559 node = LOOKUP_SIGNAL_NODE (signal_id); 1560 if (node) 1561 { 1562 if (detail && !(node->flags & G_SIGNAL_DETAILED)) 1563 g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); 1564 else if (!g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype)) 1565 g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance); 1566 else 1567 { 1568 Handler *handler = handler_new (after); 1569 1570 handler_seq_no = handler->sequential_number; 1571 handler->detail = detail; 1572 handler->closure = g_closure_ref (closure); 1573 g_closure_sink (closure); 1574 handler_insert (signal_id, instance, handler); 1575 if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (closure)) 1576 g_closure_set_marshal (closure, node->c_marshaller); 1577 } 1578 } 1579 else 1580 g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance); 1581 SIGNAL_UNLOCK (); 1582 1583 return handler_seq_no; 1584} 1585 1586gulong 1587g_signal_connect_closure (gpointer instance, 1588 const gchar *detailed_signal, 1589 GClosure *closure, 1590 gboolean after) 1591{ 1592 guint signal_id; 1593 gulong handler_seq_no = 0; 1594 GQuark detail = 0; 1595 GType itype; 1596 1597 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); 1598 g_return_val_if_fail (detailed_signal != NULL, 0); 1599 g_return_val_if_fail (closure != NULL, 0); 1600 1601 SIGNAL_LOCK (); 1602 itype = G_TYPE_FROM_INSTANCE (instance); 1603 signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE); 1604 if (signal_id) 1605 { 1606 SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id); 1607 1608 if (detail && !(node->flags & G_SIGNAL_DETAILED)) 1609 g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal); 1610 else if (!g_type_is_a (itype, node->itype)) 1611 g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); 1612 else 1613 { 1614 Handler *handler = handler_new (after); 1615 1616 handler_seq_no = handler->sequential_number; 1617 handler->detail = detail; 1618 handler->closure = g_closure_ref (closure); 1619 g_closure_sink (closure); 1620 handler_insert (signal_id, instance, handler); 1621 if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure)) 1622 g_closure_set_marshal (handler->closure, node->c_marshaller); 1623 } 1624 } 1625 else 1626 g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); 1627 SIGNAL_UNLOCK (); 1628 1629 return handler_seq_no; 1630} 1631 1632gulong 1633g_signal_connect_data (gpointer instance, 1634 const gchar *detailed_signal, 1635 GCallback c_handler, 1636 gpointer data, 1637 GClosureNotify destroy_data, 1638 GConnectFlags connect_flags) 1639{ 1640 guint signal_id; 1641 gulong handler_seq_no = 0; 1642 GQuark detail = 0; 1643 GType itype; 1644 gboolean swapped, after; 1645 1646 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); 1647 g_return_val_if_fail (detailed_signal != NULL, 0); 1648 g_return_val_if_fail (c_handler != NULL, 0); 1649 1650 swapped = (connect_flags & G_CONNECT_SWAPPED) != FALSE; 1651 after = (connect_flags & G_CONNECT_AFTER) != FALSE; 1652 1653 SIGNAL_LOCK (); 1654 itype = G_TYPE_FROM_INSTANCE (instance); 1655 signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE); 1656 if (signal_id) 1657 { 1658 SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id); 1659 1660 if (detail && !(node->flags & G_SIGNAL_DETAILED)) 1661 g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal); 1662 else if (!g_type_is_a (itype, node->itype)) 1663 g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); 1664 else 1665 { 1666 Handler *handler = handler_new (after); 1667 1668 handler_seq_no = handler->sequential_number; 1669 handler->detail = detail; 1670 handler->closure = g_closure_ref ((swapped ? g_cclosure_new_swap : g_cclosure_new) (c_handler, data, destroy_data)); 1671 g_closure_sink (handler->closure); 1672 handler_insert (signal_id, instance, handler); 1673 if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure)) 1674 g_closure_set_marshal (handler->closure, node->c_marshaller); 1675 } 1676 } 1677 else 1678 g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); 1679 SIGNAL_UNLOCK (); 1680 1681 return handler_seq_no; 1682} 1683 1684void 1685g_signal_handler_block (gpointer instance, 1686 gulong handler_id) 1687{ 1688 Handler *handler; 1689 1690 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 1691 g_return_if_fail (handler_id > 0); 1692 1693 SIGNAL_LOCK (); 1694 handler = handler_lookup (instance, handler_id, NULL); 1695 if (handler) 1696 { 1697#ifndef G_DISABLE_CHECKS 1698 if (handler->block_count >= HANDLER_MAX_BLOCK_COUNT - 1) 1699 g_error (G_STRLOC ": handler block_count overflow, %s", REPORT_BUG); 1700#endif 1701 handler->block_count += 1; 1702 } 1703 else 1704 g_warning ("%s: instance `%p' has no handler with id `%lu'", G_STRLOC, instance, handler_id); 1705 SIGNAL_UNLOCK (); 1706} 1707 1708void 1709g_signal_handler_unblock (gpointer instance, 1710 gulong handler_id) 1711{ 1712 Handler *handler; 1713 1714 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 1715 g_return_if_fail (handler_id > 0); 1716 1717 SIGNAL_LOCK (); 1718 handler = handler_lookup (instance, handler_id, NULL); 1719 if (handler) 1720 { 1721 if (handler->block_count) 1722 handler->block_count -= 1; 1723 else 1724 g_warning (G_STRLOC ": handler `%lu' of instance `%p' is not blocked", handler_id, instance); 1725 } 1726 else 1727 g_warning ("%s: instance `%p' has no handler with id `%lu'", G_STRLOC, instance, handler_id); 1728 SIGNAL_UNLOCK (); 1729} 1730 1731void 1732g_signal_handler_disconnect (gpointer instance, 1733 gulong handler_id) 1734{ 1735 Handler *handler; 1736 guint signal_id; 1737 1738 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 1739 g_return_if_fail (handler_id > 0); 1740 1741 SIGNAL_LOCK (); 1742 handler = handler_lookup (instance, handler_id, &signal_id); 1743 if (handler) 1744 { 1745 handler->sequential_number = 0; 1746 handler->block_count = 1; 1747 handler_unref_R (signal_id, instance, handler); 1748 } 1749 else 1750 g_warning ("%s: instance `%p' has no handler with id `%lu'", G_STRLOC, instance, handler_id); 1751 SIGNAL_UNLOCK (); 1752} 1753 1754gboolean 1755g_signal_handler_is_connected (gpointer instance, 1756 gulong handler_id) 1757{ 1758 Handler *handler; 1759 gboolean connected; 1760 1761 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE); 1762 1763 SIGNAL_LOCK (); 1764 handler = handler_lookup (instance, handler_id, NULL); 1765 connected = handler != NULL; 1766 SIGNAL_UNLOCK (); 1767 1768 return connected; 1769} 1770 1771void 1772g_signal_handlers_destroy (gpointer instance) 1773{ 1774 GBSearchArray *hlbsa; 1775 1776 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 1777 1778 SIGNAL_LOCK (); 1779 hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance); 1780 if (hlbsa) 1781 { 1782 guint i; 1783 1784 /* reentrancy caution, delete instance trace first */ 1785 g_hash_table_remove (g_handler_list_bsa_ht, instance); 1786 1787 for (i = 0; i < hlbsa->n_nodes; i++) 1788 { 1789 HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, &g_signal_hlbsa_bconfig, i); 1790 Handler *handler = hlist->handlers; 1791 1792 while (handler) 1793 { 1794 Handler *tmp = handler; 1795 1796 handler = tmp->next; 1797 tmp->block_count = 1; 1798 /* cruel unlink, this works because _all_ handlers vanish */ 1799 tmp->next = NULL; 1800 tmp->prev = tmp; 1801 if (tmp->sequential_number) 1802 { 1803 tmp->sequential_number = 0; 1804 handler_unref_R (0, NULL, tmp); 1805 } 1806 } 1807 } 1808 g_bsearch_array_free (hlbsa, &g_signal_hlbsa_bconfig); 1809 } 1810 SIGNAL_UNLOCK (); 1811} 1812 1813gulong 1814g_signal_handler_find (gpointer instance, 1815 GSignalMatchType mask, 1816 guint signal_id, 1817 GQuark detail, 1818 GClosure *closure, 1819 gpointer func, 1820 gpointer data) 1821{ 1822 gulong handler_seq_no = 0; 1823 1824 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); 1825 g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0); 1826 1827 if (mask & G_SIGNAL_MATCH_MASK) 1828 { 1829 HandlerMatch *mlist; 1830 1831 SIGNAL_LOCK (); 1832 mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, TRUE); 1833 if (mlist) 1834 { 1835 handler_seq_no = mlist->handler->sequential_number; 1836 handler_match_free1_R (mlist, instance); 1837 } 1838 SIGNAL_UNLOCK (); 1839 } 1840 1841 return handler_seq_no; 1842} 1843 1844static guint 1845signal_handlers_foreach_matched_R (gpointer instance, 1846 GSignalMatchType mask, 1847 guint signal_id, 1848 GQuark detail, 1849 GClosure *closure, 1850 gpointer func, 1851 gpointer data, 1852 void (*callback) (gpointer instance, 1853 gulong handler_seq_no)) 1854{ 1855 HandlerMatch *mlist; 1856 guint n_handlers = 0; 1857 1858 mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, FALSE); 1859 while (mlist) 1860 { 1861 n_handlers++; 1862 if (mlist->handler->sequential_number) 1863 { 1864 SIGNAL_UNLOCK (); 1865 callback (instance, mlist->handler->sequential_number); 1866 SIGNAL_LOCK (); 1867 } 1868 mlist = handler_match_free1_R (mlist, instance); 1869 } 1870 1871 return n_handlers; 1872} 1873 1874guint 1875g_signal_handlers_block_matched (gpointer instance, 1876 GSignalMatchType mask, 1877 guint signal_id, 1878 GQuark detail, 1879 GClosure *closure, 1880 gpointer func, 1881 gpointer data) 1882{ 1883 guint n_handlers = 0; 1884 1885 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); 1886 g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0); 1887 1888 if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) 1889 { 1890 SIGNAL_LOCK (); 1891 n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail, 1892 closure, func, data, 1893 g_signal_handler_block); 1894 SIGNAL_UNLOCK (); 1895 } 1896 1897 return n_handlers; 1898} 1899 1900guint 1901g_signal_handlers_unblock_matched (gpointer instance, 1902 GSignalMatchType mask, 1903 guint signal_id, 1904 GQuark detail, 1905 GClosure *closure, 1906 gpointer func, 1907 gpointer data) 1908{ 1909 guint n_handlers = 0; 1910 1911 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); 1912 g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0); 1913 1914 if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) 1915 { 1916 SIGNAL_LOCK (); 1917 n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail, 1918 closure, func, data, 1919 g_signal_handler_unblock); 1920 SIGNAL_UNLOCK (); 1921 } 1922 1923 return n_handlers; 1924} 1925 1926guint 1927g_signal_handlers_disconnect_matched (gpointer instance, 1928 GSignalMatchType mask, 1929 guint signal_id, 1930 GQuark detail, 1931 GClosure *closure, 1932 gpointer func, 1933 gpointer data) 1934{ 1935 guint n_handlers = 0; 1936 1937 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); 1938 g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0); 1939 1940 if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) 1941 { 1942 SIGNAL_LOCK (); 1943 n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail, 1944 closure, func, data, 1945 g_signal_handler_disconnect); 1946 SIGNAL_UNLOCK (); 1947 } 1948 1949 return n_handlers; 1950} 1951 1952gboolean 1953g_signal_has_handler_pending (gpointer instance, 1954 guint signal_id, 1955 GQuark detail, 1956 gboolean may_be_blocked) 1957{ 1958 HandlerMatch *mlist; 1959 gboolean has_pending; 1960 1961 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE); 1962 g_return_val_if_fail (signal_id > 0, FALSE); 1963 1964 SIGNAL_LOCK (); 1965 if (detail) 1966 { 1967 SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id); 1968 1969 if (!(node->flags & G_SIGNAL_DETAILED)) 1970 { 1971 g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); 1972 SIGNAL_UNLOCK (); 1973 return FALSE; 1974 } 1975 } 1976 mlist = handlers_find (instance, 1977 (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | (may_be_blocked ? 0 : G_SIGNAL_MATCH_UNBLOCKED)), 1978 signal_id, detail, NULL, NULL, NULL, TRUE); 1979 if (mlist) 1980 { 1981 has_pending = TRUE; 1982 handler_match_free1_R (mlist, instance); 1983 } 1984 else 1985 has_pending = FALSE; 1986 SIGNAL_UNLOCK (); 1987 1988 return has_pending; 1989} 1990 1991static inline gboolean 1992signal_check_skip_emission (SignalNode *node, 1993 gpointer instance, 1994 GQuark detail) 1995{ 1996 HandlerList *hlist; 1997 1998 /* are we able to check for NULL class handlers? */ 1999 if (!node->test_class_offset) 2000 return FALSE; 2001 2002 /* are there emission hooks pending? */ 2003 if (node->emission_hooks && node->emission_hooks->hooks) 2004 return FALSE; 2005 2006 /* is there a non-NULL class handler? */ 2007 if (node->test_class_offset != TEST_CLASS_MAGIC) 2008 { 2009 GTypeClass *class = G_TYPE_INSTANCE_GET_CLASS (instance, G_TYPE_FROM_INSTANCE (instance), GTypeClass); 2010 2011 if (G_STRUCT_MEMBER (gpointer, class, node->test_class_offset)) 2012 return FALSE; 2013 } 2014 2015 /* are signals being debugged? */ 2016#ifdef G_ENABLE_DEBUG 2017 IF_DEBUG (SIGNALS, g_trace_instance_signals || g_trap_instance_signals) 2018 return FALSE; 2019#endif /* G_ENABLE_DEBUG */ 2020 2021 /* is this a no-recurse signal already in emission? */ 2022 if (node->flags & G_SIGNAL_NO_RECURSE && 2023 emission_find (g_restart_emissions, node->signal_id, detail, instance)) 2024 return FALSE; 2025 2026 /* do we have pending handlers? */ 2027 hlist = handler_list_lookup (node->signal_id, instance); 2028 if (hlist && hlist->handlers) 2029 return FALSE; 2030 2031 /* none of the above, no emission required */ 2032 return TRUE; 2033} 2034 2035void 2036g_signal_emitv (const GValue *instance_and_params, 2037 guint signal_id, 2038 GQuark detail, 2039 GValue *return_value) 2040{ 2041 gpointer instance; 2042 SignalNode *node; 2043#ifdef G_ENABLE_DEBUG 2044 const GValue *param_values; 2045 guint i; 2046#endif 2047 2048 g_return_if_fail (instance_and_params != NULL); 2049 instance = g_value_peek_pointer (instance_and_params); 2050 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 2051 g_return_if_fail (signal_id > 0); 2052 2053#ifdef G_ENABLE_DEBUG 2054 param_values = instance_and_params + 1; 2055#endif 2056 2057 SIGNAL_LOCK (); 2058 node = LOOKUP_SIGNAL_NODE (signal_id); 2059 if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype)) 2060 { 2061 g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance); 2062 SIGNAL_UNLOCK (); 2063 return; 2064 } 2065#ifdef G_ENABLE_DEBUG 2066 if (detail && !(node->flags & G_SIGNAL_DETAILED)) 2067 { 2068 g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); 2069 SIGNAL_UNLOCK (); 2070 return; 2071 } 2072 for (i = 0; i < node->n_params; i++) 2073 if (!G_TYPE_CHECK_VALUE_TYPE (param_values + i, node->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE)) 2074 { 2075 g_critical ("%s: value for `%s' parameter %u for signal \"%s\" is of type `%s'", 2076 G_STRLOC, 2077 type_debug_name (node->param_types[i]), 2078 i, 2079 node->name, 2080 G_VALUE_TYPE_NAME (param_values + i)); 2081 SIGNAL_UNLOCK (); 2082 return; 2083 } 2084 if (node->return_type != G_TYPE_NONE) 2085 { 2086 if (!return_value) 2087 { 2088 g_critical ("%s: return value `%s' for signal \"%s\" is (NULL)", 2089 G_STRLOC, 2090 type_debug_name (node->return_type), 2091 node->name); 2092 SIGNAL_UNLOCK (); 2093 return; 2094 } 2095 else if (!node->accumulator && !G_TYPE_CHECK_VALUE_TYPE (return_value, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE)) 2096 { 2097 g_critical ("%s: return value `%s' for signal \"%s\" is of type `%s'", 2098 G_STRLOC, 2099 type_debug_name (node->return_type), 2100 node->name, 2101 G_VALUE_TYPE_NAME (return_value)); 2102 SIGNAL_UNLOCK (); 2103 return; 2104 } 2105 } 2106 else 2107 return_value = NULL; 2108#endif /* G_ENABLE_DEBUG */ 2109 2110 /* optimize NOP emissions */ 2111 if (signal_check_skip_emission (node, instance, detail)) 2112 { 2113 /* nothing to do to emit this signal */ 2114 SIGNAL_UNLOCK (); 2115 /* g_printerr ("omitting emission of \"%s\"\n", node->name); */ 2116 return; 2117 } 2118 2119 SIGNAL_UNLOCK (); 2120 signal_emit_unlocked_R (node, detail, instance, return_value, instance_and_params); 2121} 2122 2123void 2124g_signal_emit_valist (gpointer instance, 2125 guint signal_id, 2126 GQuark detail, 2127 va_list var_args) 2128{ 2129 GValue *instance_and_params, stack_values[MAX_STACK_VALUES], *free_me = NULL; 2130 GType signal_return_type; 2131 GValue *param_values; 2132 SignalNode *node; 2133 guint i, n_params; 2134 2135 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 2136 g_return_if_fail (signal_id > 0); 2137 2138 SIGNAL_LOCK (); 2139 node = LOOKUP_SIGNAL_NODE (signal_id); 2140 if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype)) 2141 { 2142 g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance); 2143 SIGNAL_UNLOCK (); 2144 return; 2145 } 2146#ifndef G_DISABLE_CHECKS 2147 if (detail && !(node->flags & G_SIGNAL_DETAILED)) 2148 { 2149 g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); 2150 SIGNAL_UNLOCK (); 2151 return; 2152 } 2153#endif /* !G_DISABLE_CHECKS */ 2154 2155 /* optimize NOP emissions */ 2156 if (signal_check_skip_emission (node, instance, detail)) 2157 { 2158 /* nothing to do to emit this signal */ 2159 SIGNAL_UNLOCK (); 2160 /* g_printerr ("omitting emission of \"%s\"\n", node->name); */ 2161 return; 2162 } 2163 2164 n_params = node->n_params; 2165 signal_return_type = node->return_type; 2166 if (node->n_params < MAX_STACK_VALUES) 2167 instance_and_params = stack_values; 2168 else 2169 { 2170 free_me = g_new (GValue, node->n_params + 1); 2171 instance_and_params = free_me; 2172 } 2173 param_values = instance_and_params + 1; 2174 for (i = 0; i < node->n_params; i++) 2175 { 2176 gchar *error; 2177 GType ptype = node->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE; 2178 gboolean static_scope = node->param_types[i] & G_SIGNAL_TYPE_STATIC_SCOPE; 2179 2180 param_values[i].g_type = 0; 2181 SIGNAL_UNLOCK (); 2182 g_value_init (param_values + i, ptype); 2183 G_VALUE_COLLECT (param_values + i, 2184 var_args, 2185 static_scope ? G_VALUE_NOCOPY_CONTENTS : 0, 2186 &error); 2187 if (error) 2188 { 2189 g_warning ("%s: %s", G_STRLOC, error); 2190 g_free (error); 2191 2192 /* we purposely leak the value here, it might not be 2193 * in a sane state if an error condition occoured 2194 */ 2195 while (i--) 2196 g_value_unset (param_values + i); 2197 2198 g_free (free_me); 2199 return; 2200 } 2201 SIGNAL_LOCK (); 2202 } 2203 SIGNAL_UNLOCK (); 2204 instance_and_params->g_type = 0; 2205 g_value_init (instance_and_params, G_TYPE_FROM_INSTANCE (instance)); 2206 g_value_set_instance (instance_and_params, instance); 2207 if (signal_return_type == G_TYPE_NONE) 2208 signal_emit_unlocked_R (node, detail, instance, NULL, instance_and_params); 2209 else 2210 { 2211 GValue return_value = { 0, }; 2212 gchar *error = NULL; 2213 GType rtype = signal_return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE; 2214 gboolean static_scope = signal_return_type & G_SIGNAL_TYPE_STATIC_SCOPE; 2215 2216 g_value_init (&return_value, rtype); 2217 2218 signal_emit_unlocked_R (node, detail, instance, &return_value, instance_and_params); 2219 2220 G_VALUE_LCOPY (&return_value, 2221 var_args, 2222 static_scope ? G_VALUE_NOCOPY_CONTENTS : 0, 2223 &error); 2224 if (!error) 2225 g_value_unset (&return_value); 2226 else 2227 { 2228 g_warning ("%s: %s", G_STRLOC, error); 2229 g_free (error); 2230 2231 /* we purposely leak the value here, it might not be 2232 * in a sane state if an error condition occured 2233 */ 2234 } 2235 } 2236 for (i = 0; i < n_params; i++) 2237 g_value_unset (param_values + i); 2238 g_value_unset (instance_and_params); 2239 if (free_me) 2240 g_free (free_me); 2241} 2242 2243void 2244g_signal_emit (gpointer instance, 2245 guint signal_id, 2246 GQuark detail, 2247 ...) 2248{ 2249 va_list var_args; 2250 2251 va_start (var_args, detail); 2252 g_signal_emit_valist (instance, signal_id, detail, var_args); 2253 va_end (var_args); 2254} 2255 2256void 2257g_signal_emit_by_name (gpointer instance, 2258 const gchar *detailed_signal, 2259 ...) 2260{ 2261 GQuark detail = 0; 2262 guint signal_id; 2263 2264 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 2265 g_return_if_fail (detailed_signal != NULL); 2266 2267 SIGNAL_LOCK (); 2268 signal_id = signal_parse_name (detailed_signal, G_TYPE_FROM_INSTANCE (instance), &detail, TRUE); 2269 SIGNAL_UNLOCK (); 2270 2271 if (signal_id) 2272 { 2273 va_list var_args; 2274 2275 va_start (var_args, detailed_signal); 2276 g_signal_emit_valist (instance, signal_id, detail, var_args); 2277 va_end (var_args); 2278 } 2279 else 2280 g_warning ("%s: signal name `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); 2281} 2282 2283static inline gboolean 2284accumulate (GSignalInvocationHint *ihint, 2285 GValue *return_accu, 2286 GValue *handler_return, 2287 SignalAccumulator *accumulator) 2288{ 2289 gboolean continue_emission; 2290 2291 if (!accumulator) 2292 return TRUE; 2293 2294 continue_emission = accumulator->func (ihint, return_accu, handler_return, accumulator->data); 2295 g_value_reset (handler_return); 2296 2297 return continue_emission; 2298} 2299 2300static gboolean 2301signal_emit_unlocked_R (SignalNode *node, 2302 GQuark detail, 2303 gpointer instance, 2304 GValue *emission_return, 2305 const GValue *instance_and_params) 2306{ 2307 SignalAccumulator *accumulator; 2308 Emission emission; 2309 GClosure *class_closure; 2310 HandlerList *hlist; 2311 Handler *handler_list = NULL; 2312 GValue *return_accu, accu = { 0, }; 2313 guint signal_id; 2314 gulong max_sequential_handler_number; 2315 gboolean return_value_altered = FALSE; 2316 2317#ifdef G_ENABLE_DEBUG 2318 IF_DEBUG (SIGNALS, g_trace_instance_signals == instance || g_trap_instance_signals == instance) 2319 { 2320 g_message ("%s::%s(%u) emitted (instance=%p, signal-node=%p)", 2321 g_type_name (G_TYPE_FROM_INSTANCE (instance)), 2322 node->name, detail, 2323 instance, node); 2324 if (g_trap_instance_signals == instance) 2325 G_BREAKPOINT (); 2326 } 2327#endif /* G_ENABLE_DEBUG */ 2328 2329 SIGNAL_LOCK (); 2330 signal_id = node->signal_id; 2331 if (node->flags & G_SIGNAL_NO_RECURSE) 2332 { 2333 Emission *node = emission_find (g_restart_emissions, signal_id, detail, instance); 2334 2335 if (node) 2336 { 2337 node->state = EMISSION_RESTART; 2338 SIGNAL_UNLOCK (); 2339 return return_value_altered; 2340 } 2341 } 2342 accumulator = node->accumulator; 2343 if (accumulator) 2344 { 2345 SIGNAL_UNLOCK (); 2346 g_value_init (&accu, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE); 2347 return_accu = &accu; 2348 SIGNAL_LOCK (); 2349 } 2350 else 2351 return_accu = emission_return; 2352 emission.instance = instance; 2353 emission.ihint.signal_id = node->signal_id; 2354 emission.ihint.detail = detail; 2355 emission.ihint.run_type = 0; 2356 emission.state = 0; 2357 emission.chain_type = G_TYPE_NONE; 2358 emission_push ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, &emission); 2359 class_closure = signal_lookup_closure (node, instance); 2360 2361 EMIT_RESTART: 2362 2363 if (handler_list) 2364 handler_unref_R (signal_id, instance, handler_list); 2365 max_sequential_handler_number = g_handler_sequential_number; 2366 hlist = handler_list_lookup (signal_id, instance); 2367 handler_list = hlist ? hlist->handlers : NULL; 2368 if (handler_list) 2369 handler_ref (handler_list); 2370 2371 emission.ihint.run_type = G_SIGNAL_RUN_FIRST; 2372 2373 if ((node->flags & G_SIGNAL_RUN_FIRST) && class_closure) 2374 { 2375 emission.state = EMISSION_RUN; 2376 2377 emission.chain_type = G_TYPE_FROM_INSTANCE (instance); 2378 SIGNAL_UNLOCK (); 2379 g_closure_invoke (class_closure, 2380 return_accu, 2381 node->n_params + 1, 2382 instance_and_params, 2383 &emission.ihint); 2384 if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) && 2385 emission.state == EMISSION_RUN) 2386 emission.state = EMISSION_STOP; 2387 SIGNAL_LOCK (); 2388 emission.chain_type = G_TYPE_NONE; 2389 return_value_altered = TRUE; 2390 2391 if (emission.state == EMISSION_STOP) 2392 goto EMIT_CLEANUP; 2393 else if (emission.state == EMISSION_RESTART) 2394 goto EMIT_RESTART; 2395 } 2396 2397 if (node->emission_hooks) 2398 { 2399 gboolean need_destroy, was_in_call, may_recurse = TRUE; 2400 GHook *hook; 2401 2402 emission.state = EMISSION_HOOK; 2403 hook = g_hook_first_valid (node->emission_hooks, may_recurse); 2404 while (hook) 2405 { 2406 SignalHook *signal_hook = SIGNAL_HOOK (hook); 2407 2408 if (!signal_hook->detail || signal_hook->detail == detail) 2409 { 2410 GSignalEmissionHook hook_func = (GSignalEmissionHook) hook->func; 2411 2412 was_in_call = G_HOOK_IN_CALL (hook); 2413 hook->flags |= G_HOOK_FLAG_IN_CALL; 2414 SIGNAL_UNLOCK (); 2415 need_destroy = !hook_func (&emission.ihint, node->n_params + 1, instance_and_params, hook->data); 2416 SIGNAL_LOCK (); 2417 if (!was_in_call) 2418 hook->flags &= ~G_HOOK_FLAG_IN_CALL; 2419 if (need_destroy) 2420 g_hook_destroy_link (node->emission_hooks, hook); 2421 } 2422 hook = g_hook_next_valid (node->emission_hooks, hook, may_recurse); 2423 } 2424 2425 if (emission.state == EMISSION_RESTART) 2426 goto EMIT_RESTART; 2427 } 2428 2429 if (handler_list) 2430 { 2431 Handler *handler = handler_list; 2432 2433 emission.state = EMISSION_RUN; 2434 handler_ref (handler); 2435 do 2436 { 2437 Handler *tmp; 2438 2439 if (handler->after) 2440 { 2441 handler_unref_R (signal_id, instance, handler_list); 2442 handler_list = handler; 2443 break; 2444 } 2445 else if (!handler->block_count && (!handler->detail || handler->detail == detail) && 2446 handler->sequential_number < max_sequential_handler_number) 2447 { 2448 SIGNAL_UNLOCK (); 2449 g_closure_invoke (handler->closure, 2450 return_accu, 2451 node->n_params + 1, 2452 instance_and_params, 2453 &emission.ihint); 2454 if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) && 2455 emission.state == EMISSION_RUN) 2456 emission.state = EMISSION_STOP; 2457 SIGNAL_LOCK (); 2458 return_value_altered = TRUE; 2459 2460 tmp = emission.state == EMISSION_RUN ? handler->next : NULL; 2461 } 2462 else 2463 tmp = handler->next; 2464 2465 if (tmp) 2466 handler_ref (tmp); 2467 handler_unref_R (signal_id, instance, handler_list); 2468 handler_list = handler; 2469 handler = tmp; 2470 } 2471 while (handler); 2472 2473 if (emission.state == EMISSION_STOP) 2474 goto EMIT_CLEANUP; 2475 else if (emission.state == EMISSION_RESTART) 2476 goto EMIT_RESTART; 2477 } 2478 2479 emission.ihint.run_type = G_SIGNAL_RUN_LAST; 2480 2481 if ((node->flags & G_SIGNAL_RUN_LAST) && class_closure) 2482 { 2483 emission.state = EMISSION_RUN; 2484 2485 emission.chain_type = G_TYPE_FROM_INSTANCE (instance); 2486 SIGNAL_UNLOCK (); 2487 g_closure_invoke (class_closure, 2488 return_accu, 2489 node->n_params + 1, 2490 instance_and_params, 2491 &emission.ihint); 2492 if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) && 2493 emission.state == EMISSION_RUN) 2494 emission.state = EMISSION_STOP; 2495 SIGNAL_LOCK (); 2496 emission.chain_type = G_TYPE_NONE; 2497 return_value_altered = TRUE; 2498 2499 if (emission.state == EMISSION_STOP) 2500 goto EMIT_CLEANUP; 2501 else if (emission.state == EMISSION_RESTART) 2502 goto EMIT_RESTART; 2503 } 2504 2505 if (handler_list) 2506 { 2507 Handler *handler = handler_list; 2508 2509 emission.state = EMISSION_RUN; 2510 handler_ref (handler); 2511 do 2512 { 2513 Handler *tmp; 2514 2515 if (handler->after && !handler->block_count && (!handler->detail || handler->detail == detail) && 2516 handler->sequential_number < max_sequential_handler_number) 2517 { 2518 SIGNAL_UNLOCK (); 2519 g_closure_invoke (handler->closure, 2520 return_accu, 2521 node->n_params + 1, 2522 instance_and_params, 2523 &emission.ihint); 2524 if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) && 2525 emission.state == EMISSION_RUN) 2526 emission.state = EMISSION_STOP; 2527 SIGNAL_LOCK (); 2528 return_value_altered = TRUE; 2529 2530 tmp = emission.state == EMISSION_RUN ? handler->next : NULL; 2531 } 2532 else 2533 tmp = handler->next; 2534 2535 if (tmp) 2536 handler_ref (tmp); 2537 handler_unref_R (signal_id, instance, handler); 2538 handler = tmp; 2539 } 2540 while (handler); 2541 2542 if (emission.state == EMISSION_STOP) 2543 goto EMIT_CLEANUP; 2544 else if (emission.state == EMISSION_RESTART) 2545 goto EMIT_RESTART; 2546 } 2547 2548 EMIT_CLEANUP: 2549 2550 emission.ihint.run_type = G_SIGNAL_RUN_CLEANUP; 2551 2552 if ((node->flags & G_SIGNAL_RUN_CLEANUP) && class_closure) 2553 { 2554 gboolean need_unset = FALSE; 2555 2556 emission.state = EMISSION_STOP; 2557 2558 emission.chain_type = G_TYPE_FROM_INSTANCE (instance); 2559 SIGNAL_UNLOCK (); 2560 if (node->return_type != G_TYPE_NONE && !accumulator) 2561 { 2562 g_value_init (&accu, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE); 2563 need_unset = TRUE; 2564 } 2565 g_closure_invoke (class_closure, 2566 node->return_type != G_TYPE_NONE ? &accu : NULL, 2567 node->n_params + 1, 2568 instance_and_params, 2569 &emission.ihint); 2570 if (need_unset) 2571 g_value_unset (&accu); 2572 SIGNAL_LOCK (); 2573 emission.chain_type = G_TYPE_NONE; 2574 2575 if (emission.state == EMISSION_RESTART) 2576 goto EMIT_RESTART; 2577 } 2578 2579 if (handler_list) 2580 handler_unref_R (signal_id, instance, handler_list); 2581 2582 emission_pop ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, &emission); 2583 SIGNAL_UNLOCK (); 2584 if (accumulator) 2585 g_value_unset (&accu); 2586 2587 return return_value_altered; 2588} 2589 2590static const gchar* 2591type_debug_name (GType type) 2592{ 2593 if (type) 2594 { 2595 const char *name = g_type_name (type & ~G_SIGNAL_TYPE_STATIC_SCOPE); 2596 return name ? name : "<unknown>"; 2597 } 2598 else 2599 return "<invalid>"; 2600} 2601 2602gboolean 2603g_signal_accumulator_true_handled (GSignalInvocationHint *ihint, 2604 GValue *return_accu, 2605 const GValue *handler_return, 2606 gpointer dummy) 2607{ 2608 gboolean continue_emission; 2609 gboolean signal_handled; 2610 2611 signal_handled = g_value_get_boolean (handler_return); 2612 g_value_set_boolean (return_accu, signal_handled); 2613 continue_emission = !signal_handled; 2614 2615 return continue_emission; 2616} 2617 2618/* --- compile standard marshallers --- */ 2619#include "gobject.h" 2620#include "genums.h" 2621#include "gmarshal.c" 2622 2623#define __G_SIGNAL_C__ 2624#include "gobjectaliasdef.c" 2625