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