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