gsignal.c revision 83c45024e3d3a56ac17eb08dcddae048005bbb71
1/* GObject - GLib Type, Object, Parameter and Signal Library 2 * Copyright (C) 2000 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#include <string.h> 23 24#include "gsignal.h" 25 26#include "gbsearcharray.h" 27 28 29/* pre allocation configurations 30 */ 31#define BSA_PRE_ALLOC (20) 32#define HANDLER_PRE_ALLOC (48) 33#define EMISSION_PRE_ALLOC (16) 34 35#define TIGHT_MEMORY (1) 36 37#define REPORT_BUG "please report occourance circumstances to gtk-devel-list@gnome.org" 38 39 40/* --- generic allocation --- */ 41/* we can special case allocations generically by replacing 42 * these functions with more speed/memory aware variants 43 */ 44static inline gpointer 45g_generic_node_alloc (GTrashStack **trash_stack_p, 46 guint sizeof_node, 47 guint nodes_pre_alloc) 48{ 49 gpointer node = g_trash_stack_pop (trash_stack_p); 50 51 if (!node) 52 { 53 guint8 *block; 54 55 nodes_pre_alloc = MAX (nodes_pre_alloc, 1); 56 block = g_malloc (sizeof_node * nodes_pre_alloc); 57 while (--nodes_pre_alloc) 58 { 59 g_trash_stack_push (trash_stack_p, block); 60 block += sizeof_node; 61 } 62 node = block; 63 } 64 65 return node; 66} 67static inline void 68g_generic_node_free (GTrashStack **trash_stack_p, 69 gpointer node) 70{ 71 g_trash_stack_push (trash_stack_p, node); 72} 73 74 75/* --- typedefs --- */ 76typedef struct _SignalNode SignalNode; 77typedef struct _SignalKey SignalKey; 78typedef struct _Emission Emission; 79typedef struct _Handler Handler; 80typedef struct _HandlerList HandlerList; 81typedef struct _HandlerMatch HandlerMatch; 82typedef enum 83{ 84 EMISSION_STOP, 85 EMISSION_RUN, 86 EMISSION_HOOK, 87 EMISSION_RESTART 88} EmissionState; 89 90 91/* --- prototypes --- */ 92static inline guint signal_id_lookup (GQuark quark, 93 GType itype); 94static void signal_destroy_R (SignalNode *signal_node); 95static inline HandlerList* handler_list_ensure (guint signal_id, 96 gpointer instance); 97static inline HandlerList* handler_list_lookup (guint signal_id, 98 gpointer instance); 99static inline Handler* handler_new (gboolean after); 100static void handler_insert (guint signal_id, 101 gpointer instance, 102 Handler *handler); 103static Handler* handler_lookup (gpointer instance, 104 guint handler_id, 105 guint *signal_id_p); 106static inline HandlerMatch* handler_match_prepend (HandlerMatch *list, 107 Handler *handler, 108 guint signal_id); 109static inline HandlerMatch* handler_match_free1_R (HandlerMatch *node, 110 gpointer instance); 111static HandlerMatch* handlers_find (gpointer instance, 112 GSignalMatchType mask, 113 guint signal_id, 114 GQuark detail, 115 GClosure *closure, 116 gpointer func, 117 gpointer data, 118 gboolean one_and_only); 119static inline void handler_ref (Handler *handler); 120static inline void handler_unref_R (guint signal_id, 121 gpointer instance, 122 Handler *handler); 123static inline void emission_push (Emission **emission_list_p, 124 guint signal_id, 125 GQuark detail, 126 gpointer instance, 127 EmissionState *state_p); 128static inline void emission_pop (Emission **emission_list_p, 129 EmissionState *state_p); 130static inline Emission* emission_find (Emission *emission_list, 131 guint signal_id, 132 GQuark detail, 133 gpointer instance); 134static void signal_emit_R (SignalNode *node, 135 GQuark detail, 136 gpointer instance, 137 GValue *return_value, 138 const GValue *instance_and_params); 139 140 141/* --- structures --- */ 142struct _SignalNode 143{ 144 /* permanent portion */ 145 guint signal_id; 146 GType itype; 147 gchar *name; 148 guint destroyed : 1; 149 150 /* reinitializable portion */ 151 guint flags : 8; 152 guint n_params : 8; 153 GType *param_types; 154 GType return_type; 155 GClosure *class_closure; 156 GSignalAccumulator accumulator; 157 GSignalCMarshaller c_marshaller; 158 GHookList *emission_hooks; 159}; 160 161struct _SignalKey 162{ 163 GType itype; 164 GQuark quark; 165 guint signal_id; 166}; 167 168struct _Emission 169{ 170 Emission *next; 171 guint signal_id; 172 GQuark detail; 173 gpointer instance; 174 EmissionState *state_p; 175}; 176 177struct _HandlerList 178{ 179 guint signal_id; 180 Handler *handlers; 181}; 182struct _Handler 183{ 184 guint id; 185 Handler *next; 186 Handler *prev; 187 GQuark detail; 188 guint ref_count : 16; 189#define HANDLER_MAX_REF_COUNT (1 << 16) 190 guint block_count : 12; 191#define HANDLER_MAX_BLOCK_COUNT (1 << 12) 192 guint after : 1; 193 GClosure *closure; 194}; 195struct _HandlerMatch 196{ 197 Handler *handler; 198 HandlerMatch *next; 199 union { 200 guint signal_id; 201 gpointer dummy; 202 } d; 203}; 204 205 206/* --- variables --- */ 207static GBSearchArray g_signal_key_bsa = { NULL, 0, 0, 0, NULL }; 208static GHashTable *g_handler_list_bsa_ht = NULL; 209static Emission *g_recursive_emissions = NULL; 210static Emission *g_restart_emissions = NULL; 211static GTrashStack *g_bsa_ts = NULL; 212static GTrashStack *g_handler_ts = NULL; 213static GTrashStack *g_emission_ts = NULL; 214G_LOCK_DEFINE_STATIC (g_signal_mutex); 215 216 217/* --- signal nodes --- */ 218static guint g_n_signal_nodes = 0; 219static SignalNode **g_signal_nodes = NULL; 220 221static inline SignalNode* 222LOOKUP_SIGNAL_NODE (register guint signal_id) 223{ 224 if (signal_id < g_n_signal_nodes) 225 return g_signal_nodes[signal_id]; 226 else 227 return NULL; 228} 229 230 231/* --- functions --- */ 232static inline guint 233signal_id_lookup (GQuark quark, 234 GType itype) 235{ 236 do 237 { 238 SignalKey key, *signal_key; 239 240 key.itype = itype; 241 key.quark = quark; 242 243 signal_key = g_bsearch_array_lookup (&g_signal_key_bsa, &key); 244 245 if (signal_key) 246 return signal_key->signal_id; 247 248 itype = g_type_parent (itype); 249 } 250 while (itype); 251 252 return 0; 253} 254 255static gint 256handler_lists_cmp (gconstpointer node1, 257 gconstpointer node2) 258{ 259 const HandlerList *hlist1 = node1, *hlist2 = node2; 260 261 return G_BSEARCH_ARRAY_CMP (hlist1->signal_id, hlist2->signal_id); 262} 263 264static inline HandlerList* 265handler_list_ensure (guint signal_id, 266 gpointer instance) 267{ 268 GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance); 269 HandlerList key; 270 271 if (!hlbsa) 272 { 273 hlbsa = g_generic_node_alloc (&g_bsa_ts, 274 sizeof (GBSearchArray), 275 BSA_PRE_ALLOC); 276 hlbsa->cmp_func = handler_lists_cmp; 277 hlbsa->sizeof_node = sizeof (HandlerList); 278 hlbsa->flags = G_BSEARCH_DEFER_SHRINK; 279 hlbsa->n_nodes = 0; 280 hlbsa->nodes = NULL; 281 g_hash_table_insert (g_handler_list_bsa_ht, instance, hlbsa); 282 } 283 key.signal_id = signal_id; 284 key.handlers = NULL; 285 286 return g_bsearch_array_insert (hlbsa, &key, FALSE); 287} 288 289static inline HandlerList* 290handler_list_lookup (guint signal_id, 291 gpointer instance) 292{ 293 GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance); 294 HandlerList key; 295 296 key.signal_id = signal_id; 297 298 return hlbsa ? g_bsearch_array_lookup (hlbsa, &key) : NULL; 299} 300 301static Handler* 302handler_lookup (gpointer instance, 303 guint handler_id, 304 guint *signal_id_p) 305{ 306 GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance); 307 308 if (hlbsa) 309 { 310 guint i; 311 312 for (i = 0; i < hlbsa->n_nodes; i++) 313 { 314 HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i); 315 Handler *handler; 316 317 for (handler = hlist->handlers; handler; handler = handler->next) 318 if (handler->id == handler_id) 319 { 320 if (signal_id_p) 321 *signal_id_p = hlist->signal_id; 322 323 return handler; 324 } 325 } 326 } 327 328 return NULL; 329} 330 331static inline HandlerMatch* 332handler_match_prepend (HandlerMatch *list, 333 Handler *handler, 334 guint signal_id) 335{ 336 HandlerMatch *node; 337 338 /* yeah, we could use our own memchunk here, introducing yet more 339 * rarely used cached nodes and extra allocation overhead. 340 * instead, we use GList* nodes, since they are exactly the size 341 * we need and are already cached. g_signal_init() asserts this. 342 */ 343 node = (HandlerMatch*) g_list_alloc (); 344 node->handler = handler; 345 node->next = list; 346 node->d.signal_id = signal_id; 347 handler_ref (handler); 348 349 return node; 350} 351static inline HandlerMatch* 352handler_match_free1_R (HandlerMatch *node, 353 gpointer instance) 354{ 355 HandlerMatch *next = node->next; 356 357 handler_unref_R (node->d.signal_id, instance, node->handler); 358 g_list_free_1 ((GList*) node); 359 360 return next; 361} 362 363static HandlerMatch* 364handlers_find (gpointer instance, 365 GSignalMatchType mask, 366 guint signal_id, 367 GQuark detail, 368 GClosure *closure, 369 gpointer func, 370 gpointer data, 371 gboolean one_and_only) 372{ 373 HandlerMatch *mlist = NULL; 374 375 if (mask & G_SIGNAL_MATCH_ID) 376 { 377 HandlerList *hlist = handler_list_lookup (signal_id, instance); 378 Handler *handler; 379 SignalNode *node; 380 381 if (mask & G_SIGNAL_MATCH_FUNC) 382 { 383 node = LOOKUP_SIGNAL_NODE (signal_id); 384 if (!node || !node->c_marshaller) 385 return NULL; 386 } 387 388 mask = ~mask; 389 for (handler = hlist ? hlist->handlers : NULL; handler; handler = handler->next) 390 if (handler->id && 391 ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) && 392 ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) && 393 ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) && 394 ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) && 395 ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller && 396 handler->closure->meta_marshal == 0 && 397 ((GCClosure*) handler->closure)->callback == func))) 398 { 399 mlist = handler_match_prepend (mlist, handler, signal_id); 400 if (one_and_only) 401 return mlist; 402 } 403 } 404 else 405 { 406 GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance); 407 408 mask = ~mask; 409 if (hlbsa) 410 { 411 guint i; 412 413 for (i = 0; i < hlbsa->n_nodes; i++) 414 { 415 HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i); 416 SignalNode *node; 417 Handler *handler; 418 419 if (!(mask & G_SIGNAL_MATCH_FUNC)) 420 { 421 node = LOOKUP_SIGNAL_NODE (hlist->signal_id); 422 if (!node->c_marshaller) 423 continue; 424 } 425 426 for (handler = hlist->handlers; handler; handler = handler->next) 427 if (handler->id && 428 ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) && 429 ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) && 430 ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) && 431 ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) && 432 ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller && 433 handler->closure->meta_marshal == 0 && 434 ((GCClosure*) handler->closure)->callback == func))) 435 { 436 mlist = handler_match_prepend (mlist, handler, signal_id); 437 if (one_and_only) 438 return mlist; 439 } 440 } 441 } 442 } 443 444 return mlist; 445} 446 447static inline Handler* 448handler_new (gboolean after) 449{ 450 static guint handler_id = 1; 451 Handler *handler = g_generic_node_alloc (&g_handler_ts, 452 sizeof (Handler), 453 HANDLER_PRE_ALLOC); 454#ifndef G_DISABLE_CHECKS 455 if (handler_id == 0) 456 g_error (G_STRLOC ": handler id overflow, %s", REPORT_BUG); 457#endif 458 459 handler->id = handler_id++; 460 handler->prev = NULL; 461 handler->next = NULL; 462 handler->detail = 0; 463 handler->ref_count = 1; 464 handler->block_count = 0; 465 handler->after = after != FALSE; 466 handler->closure = NULL; 467 468 return handler; 469} 470 471static inline void 472handler_ref (Handler *handler) 473{ 474 g_return_if_fail (handler->ref_count > 0); 475 476#ifndef G_DISABLE_CHECKS 477 if (handler->ref_count >= HANDLER_MAX_REF_COUNT - 1) 478 g_error (G_STRLOC ": handler ref_count overflow, %s", REPORT_BUG); 479#endif 480 481 handler->ref_count += 1; 482} 483 484static inline void 485handler_unref_R (guint signal_id, 486 gpointer instance, 487 Handler *handler) 488{ 489 g_return_if_fail (handler->ref_count > 0); 490 491 handler->ref_count -= 1; 492 if (!handler->ref_count) 493 { 494 if (handler->next) 495 handler->next->prev = handler->prev; 496 if (handler->prev) /* watch out for g_signal_handlers_destroy()! */ 497 handler->prev->next = handler->next; 498 else 499 { 500 HandlerList *hlist = handler_list_lookup (signal_id, instance); 501 502 hlist->handlers = handler->next; 503 } 504 G_UNLOCK (g_signal_mutex); 505 g_closure_unref (handler->closure); 506 G_LOCK (g_signal_mutex); 507 g_generic_node_free (&g_handler_ts, handler); 508 } 509} 510 511static void 512handler_insert (guint signal_id, 513 gpointer instance, 514 Handler *handler) 515{ 516 HandlerList *hlist; 517 518 g_assert (handler->prev == NULL && handler->next == NULL); // FIXME: paranoid 519 520 hlist = handler_list_ensure (signal_id, instance); 521 if (!hlist->handlers) 522 hlist->handlers = handler; 523 else if (hlist->handlers->after && !handler->after) 524 { 525 handler->next = hlist->handlers; 526 hlist->handlers->prev = handler; 527 hlist->handlers = handler; 528 } 529 else 530 { 531 Handler *tmp = hlist->handlers; 532 533 if (handler->after) 534 while (tmp->next) 535 tmp = tmp->next; 536 else 537 while (tmp->next && !tmp->next->after) 538 tmp = tmp->next; 539 if (tmp->next) 540 tmp->next->prev = handler; 541 handler->next = tmp->next; 542 handler->prev = tmp; 543 tmp->next = handler; 544 } 545} 546 547static inline void 548emission_push (Emission **emission_list_p, 549 guint signal_id, 550 GQuark detail, 551 gpointer instance, 552 EmissionState *state_p) 553{ 554 Emission *emission = g_generic_node_alloc (&g_emission_ts, 555 sizeof (Emission), 556 EMISSION_PRE_ALLOC); 557 emission->next = *emission_list_p; 558 emission->signal_id = signal_id; 559 emission->detail = detail; 560 emission->instance = instance; 561 emission->state_p = state_p; 562 *emission_list_p = emission; 563} 564 565static inline void 566emission_pop (Emission **emission_list_p, 567 EmissionState *state_p) 568{ 569 Emission **loc = emission_list_p, *emission = *loc; 570 571 while (emission->state_p != state_p) 572 { 573 loc = &emission->next; 574 emission = *loc; 575 } 576 *loc = emission->next; 577 g_generic_node_free (&g_emission_ts, emission); 578} 579 580static inline Emission* 581emission_find (Emission *emission_list, 582 guint signal_id, 583 GQuark detail, 584 gpointer instance) 585{ 586 Emission *emission; 587 588 for (emission = emission_list; emission; emission = emission->next) 589 if (emission->instance == instance && 590 emission->signal_id == signal_id && 591 emission->detail == detail) 592 return emission; 593 return NULL; 594} 595 596static gint 597signal_key_cmp (gconstpointer node1, 598 gconstpointer node2) 599{ 600 const SignalKey *key1 = node1, *key2 = node2; 601 602 if (key1->itype == key2->itype) 603 return G_BSEARCH_ARRAY_CMP (key1->quark, key2->quark); 604 else 605 return G_BSEARCH_ARRAY_CMP (key1->itype, key2->itype); 606} 607 608void 609g_signal_init (void) /* sync with gtype.c */ 610{ 611 G_LOCK (g_signal_mutex); 612 if (!g_n_signal_nodes) 613 { 614 /* handler_id_node_prepend() requires this */ 615 g_assert (sizeof (GList) == sizeof (HandlerMatch)); 616 617 /* setup signal key array */ 618 g_signal_key_bsa.cmp_func = signal_key_cmp; 619 g_signal_key_bsa.sizeof_node = sizeof (SignalKey); 620 g_signal_key_bsa.flags = 0; /* alloc-only */ 621 622 /* setup handler list binary searchable array hash table (in german, that'd be one word ;) */ 623 g_handler_list_bsa_ht = g_hash_table_new (g_direct_hash, NULL); 624 625 /* invalid (0) signal_id */ 626 g_n_signal_nodes = 1; 627 g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes); 628 g_signal_nodes[0] = NULL; 629 } 630 G_UNLOCK (g_signal_mutex); 631} 632 633void 634_g_signals_destroy (GType itype) 635{ 636 guint i; 637 638 G_LOCK (g_signal_mutex); 639 for (i = 1; i < g_n_signal_nodes; i++) 640 { 641 SignalNode *node = g_signal_nodes[i]; 642 643 if (node->itype == itype) 644 { 645 if (node->destroyed) 646 g_warning (G_STRLOC ": signal \"%s\" of type `%s' already destroyed", 647 node->name, 648 g_type_name (node->itype)); 649 else 650 signal_destroy_R (node); 651 } 652 } 653 G_UNLOCK (g_signal_mutex); 654} 655 656void 657g_signal_stop_emission (gpointer instance, 658 guint signal_id, 659 GQuark detail) 660{ 661 SignalNode *node; 662 663 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 664 g_return_if_fail (signal_id > 0); 665 666 G_LOCK (g_signal_mutex); 667 node = LOOKUP_SIGNAL_NODE (signal_id); 668 if (node && detail && !(node->flags & G_SIGNAL_DETAILED)) 669 { 670 g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); 671 G_UNLOCK (g_signal_mutex); 672 return; 673 } 674 if (node && g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype)) 675 { 676 Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions; 677 Emission *emission = emission_find (emission_list, signal_id, detail, instance); 678 679 if (emission) 680 { 681 if (*emission->state_p == EMISSION_HOOK) 682 g_warning (G_STRLOC ": emission of signal \"%s\" for instance `%p' cannot be stopped from emission hook", 683 node->name, instance); 684 else if (*emission->state_p == EMISSION_RUN) 685 *emission->state_p = EMISSION_STOP; 686 } 687 else 688 g_warning (G_STRLOC ": no emission of signal \"%s\" to stop for instance `%p'", 689 node->name, instance); 690 } 691 else 692 g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance); 693 G_UNLOCK (g_signal_mutex); 694} 695 696static inline guint 697signal_parse_name (const gchar *name, 698 GType itype, 699 GQuark *detail_p, 700 gboolean force_quark) 701{ 702 const gchar *colon = strchr (name, ':'); 703 guint signal_id; 704 705 if (!colon) 706 { 707 signal_id = signal_id_lookup (g_quark_try_string (name), itype); 708 if (signal_id && detail_p) 709 *detail_p = 0; 710 } 711 else if (colon[1] == ':') 712 { 713 gchar buffer[32]; 714 guint l = colon - name; 715 716 if (l < 32) 717 { 718 memcpy (buffer, name, l); 719 buffer[l] = 0; 720 signal_id = signal_id_lookup (g_quark_try_string (buffer), itype); 721 } 722 else 723 { 724 gchar *signal = g_new (gchar, l + 1); 725 726 memcpy (signal, name, l); 727 signal[l] = 0; 728 signal_id = signal_id_lookup (g_quark_try_string (signal), itype); 729 g_free (signal); 730 } 731 732 if (signal_id && detail_p) 733 *detail_p = colon[2] ? (force_quark ? g_quark_from_string : g_quark_try_string) (colon + 2) : 0; 734 } 735 else 736 signal_id = 0; 737 return signal_id; 738} 739 740gboolean 741g_signal_parse_name (const gchar *detailed_signal, 742 GType itype, 743 guint *signal_id_p, 744 GQuark *detail_p, 745 gboolean force_detail_quark) 746{ 747 GQuark detail = 0; 748 guint signal_id; 749 750 g_return_val_if_fail (detailed_signal != NULL, FALSE); 751 g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), FALSE); 752 753 G_LOCK (g_signal_mutex); 754 signal_id = signal_parse_name (detailed_signal, itype, &detail, force_detail_quark); 755 G_UNLOCK (g_signal_mutex); 756 757 if (signal_id) 758 { 759 if (signal_id_p) 760 *signal_id_p = signal_id; 761 if (detail_p) 762 *detail_p = detail; 763 764 return TRUE; 765 } 766 else 767 return FALSE; 768} 769 770guint 771g_signal_lookup (const gchar *name, 772 GType itype) 773{ 774 guint signal_id; 775 776 g_return_val_if_fail (name != NULL, 0); 777 g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0); 778 779 G_LOCK (g_signal_mutex); 780 signal_id = signal_id_lookup (g_quark_try_string (name), itype); 781 G_UNLOCK (g_signal_mutex); 782 783 return signal_id; 784} 785 786gchar* 787g_signal_name (guint signal_id) 788{ 789 SignalNode *node; 790 gchar *name; 791 792 G_LOCK (g_signal_mutex); 793 node = LOOKUP_SIGNAL_NODE (signal_id); 794 name = node ? node->name : NULL; 795 G_UNLOCK (g_signal_mutex); 796 797 return name; 798} 799 800void 801g_signal_query (guint signal_id, 802 GSignalQuery *query) 803{ 804 SignalNode *node; 805 806 g_return_if_fail (query != NULL); 807 808 G_LOCK (g_signal_mutex); 809 node = LOOKUP_SIGNAL_NODE (signal_id); 810 if (!node || node->destroyed) 811 query->signal_id = 0; 812 else 813 { 814 query->signal_id = node->signal_id; 815 query->signal_name = node->name; 816 query->itype = node->itype; 817 query->signal_flags = node->flags; 818 query->return_type = node->return_type; 819 query->n_params = node->n_params; 820 query->param_types = node->param_types; 821 } 822 G_UNLOCK (g_signal_mutex); 823} 824 825guint* 826g_signal_list_ids (GType itype, 827 guint *n_ids) 828{ 829 SignalKey *keys; 830 GArray *result; 831 guint n_nodes; 832 guint i; 833 834 g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), NULL); 835 g_return_val_if_fail (n_ids != NULL, NULL); 836 837 G_LOCK (g_signal_mutex); 838 839 keys = g_signal_key_bsa.nodes; 840 n_nodes = g_signal_key_bsa.n_nodes; 841 result = g_array_new (FALSE, FALSE, sizeof (guint)); 842 843 for (i = 0; i < n_nodes; i++) 844 if (keys[i].itype == itype) 845 { 846 gchar *name = g_quark_to_string (keys[i].quark); 847 848 /* Signal names with "_" in them are aliases to the same 849 * name with "-" instead of "_". 850 */ 851 if (!strchr (name, '_')) 852 g_array_append_val (result, keys[i].signal_id); 853 } 854 855 *n_ids = result->len; 856 857 G_UNLOCK (g_signal_mutex); 858 859 return (guint *) g_array_free (result, FALSE); 860} 861 862guint 863g_signal_newv (const gchar *signal_name, 864 GType itype, 865 GSignalFlags signal_flags, 866 GClosure *class_closure, 867 GSignalAccumulator accumulator, 868 GSignalCMarshaller c_marshaller, 869 GType return_type, 870 guint n_params, 871 GType *param_types) 872{ 873 gchar *name; 874 guint signal_id, i; 875 SignalNode *node; 876 877 g_return_val_if_fail (signal_name != NULL, 0); 878 g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0); 879 if (n_params) 880 g_return_val_if_fail (param_types != NULL, 0); 881 if (return_type != G_TYPE_NONE) 882 g_return_val_if_fail (accumulator == NULL, 0); 883 884 name = g_strdup (signal_name); 885 g_strdelimit (name, G_STR_DELIMITERS ":^", '_'); // FIXME do character checks like for types 886 887 G_LOCK (g_signal_mutex); 888 889 signal_id = signal_id_lookup (g_quark_try_string (name), itype); 890 node = LOOKUP_SIGNAL_NODE (signal_id); 891 if (node && !node->destroyed) 892 { 893 g_warning (G_STRLOC ": signal \"%s\" already exists in the `%s' %s", 894 name, 895 g_type_name (node->itype), 896 G_TYPE_IS_INTERFACE (node->itype) ? "interface" : "class ancestry"); 897 g_free (name); 898 G_UNLOCK (g_signal_mutex); 899 return 0; 900 } 901 if (node && node->itype != itype) 902 { 903 g_warning (G_STRLOC ": signal \"%s\" for type `%s' was previously created for type `%s'", 904 name, 905 g_type_name (itype), 906 g_type_name (node->itype)); 907 g_free (name); 908 G_UNLOCK (g_signal_mutex); 909 return 0; 910 } 911 for (i = 0; i < n_params; i++) 912 if (!G_TYPE_IS_VALUE (param_types[i]) || 913 param_types[i] == G_TYPE_ENUM || param_types[i] == G_TYPE_FLAGS) /* FIXME: kludge */ 914 { 915 g_warning (G_STRLOC ": parameter %d of type `%s' for signal \"%s::%s\" is not a value type", 916 i + 1, g_type_name (param_types[i]), g_type_name (itype), name); 917 g_free (name); 918 G_UNLOCK (g_signal_mutex); 919 return 0; 920 } 921 if (return_type != G_TYPE_NONE && !G_TYPE_IS_VALUE (return_type)) 922 { 923 g_warning (G_STRLOC ": return value of type `%s' for signal \"%s::%s\" is not a value type", 924 g_type_name (param_types[i]), g_type_name (itype), name); 925 g_free (name); 926 G_UNLOCK (g_signal_mutex); 927 return 0; 928 } 929 930 /* setup permanent portion of signal node */ 931 if (!node) 932 { 933 SignalKey key; 934 935 signal_id = g_n_signal_nodes++; 936 node = g_new (SignalNode, 1); 937 node->signal_id = signal_id; 938 g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes); 939 g_signal_nodes[signal_id] = node; 940 node->itype = itype; 941 node->name = name; 942 key.itype = itype; 943 key.quark = g_quark_from_string (node->name); 944 key.signal_id = signal_id; 945 g_bsearch_array_insert (&g_signal_key_bsa, &key, FALSE); 946 g_strdelimit (node->name, "_", '-'); 947 key.quark = g_quark_from_static_string (node->name); 948 g_bsearch_array_insert (&g_signal_key_bsa, &key, FALSE); 949 } 950 node->destroyed = FALSE; 951 952 /* setup reinitializable portion */ 953 node->flags = signal_flags & G_SIGNAL_FLAGS_MASK; 954 node->n_params = n_params; 955 node->param_types = g_memdup (param_types, sizeof (GType) * n_params); 956 node->return_type = return_type; 957 node->class_closure = class_closure ? g_closure_ref (class_closure) : NULL; 958 node->accumulator = accumulator; 959 node->c_marshaller = c_marshaller; 960 node->emission_hooks = NULL; 961 if (node->c_marshaller && class_closure && G_CLOSURE_NEEDS_MARSHAL (class_closure)) 962 g_closure_set_marshal (class_closure, node->c_marshaller); 963 964 G_UNLOCK (g_signal_mutex); 965 return signal_id; 966} 967 968static void 969signal_destroy_R (SignalNode *signal_node) 970{ 971 SignalNode node = *signal_node; 972 973 signal_node->destroyed = TRUE; 974 975 /* reentrancy caution, zero out real contents first */ 976 signal_node->n_params = 0; 977 signal_node->param_types = NULL; 978 signal_node->return_type = 0; 979 signal_node->class_closure = NULL; 980 signal_node->accumulator = NULL; 981 signal_node->c_marshaller = NULL; 982 signal_node->emission_hooks = NULL; 983 984#ifndef G_DISABLE_CHECKS 985 /* check current emissions */ 986 { 987 Emission *emission; 988 989 for (emission = (node.flags & G_SIGNAL_NO_RECURSE) ? g_restart_emissions : g_recursive_emissions; 990 emission; emission = emission->next) 991 if (emission->signal_id == node.signal_id) 992 g_critical (G_STRLOC ": signal \"%s\" being destroyed is currently in emission (instance `%p')", 993 node.name, emission->instance); 994 } 995#endif 996 997 /* free contents that need to 998 */ 999 G_UNLOCK (g_signal_mutex); 1000 g_free (node.param_types); 1001 g_closure_unref (node.class_closure); 1002 if (node.emission_hooks) 1003 { 1004 g_hook_list_clear (node.emission_hooks); 1005 g_free (node.emission_hooks); 1006 } 1007 G_LOCK (g_signal_mutex); 1008} 1009 1010guint 1011g_signal_connect_closure_by_id (gpointer instance, 1012 guint signal_id, 1013 GQuark detail, 1014 GClosure *closure, 1015 gboolean after) 1016{ 1017 SignalNode *node; 1018 guint handler_id = 0; 1019 1020 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); 1021 g_return_val_if_fail (signal_id > 0, 0); 1022 g_return_val_if_fail (closure != NULL, 0); 1023 1024 G_LOCK (g_signal_mutex); 1025 node = LOOKUP_SIGNAL_NODE (signal_id); 1026 if (node && detail && !(node->flags & G_SIGNAL_DETAILED)) 1027 { 1028 g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); 1029 G_UNLOCK (g_signal_mutex); 1030 return 0; 1031 } 1032 if (node && g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype)) 1033 { 1034 Handler *handler = handler_new (after); 1035 1036 handler_id = handler->id; 1037 handler->detail = detail; 1038 handler->closure = g_closure_ref (closure); 1039 handler_insert (signal_id, instance, handler); 1040 if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (closure)) 1041 g_closure_set_marshal (closure, node->c_marshaller); 1042 } 1043 else 1044 g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance); 1045 G_UNLOCK (g_signal_mutex); 1046 1047 return handler_id; 1048} 1049 1050void 1051g_signal_handler_block (gpointer instance, 1052 guint handler_id) 1053{ 1054 Handler *handler; 1055 1056 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 1057 g_return_if_fail (handler_id > 0); 1058 1059 G_LOCK (g_signal_mutex); 1060 handler = handler_lookup (instance, handler_id, NULL); 1061 if (handler) 1062 { 1063#ifndef G_DISABLE_CHECKS 1064 if (handler->block_count >= HANDLER_MAX_BLOCK_COUNT - 1) 1065 g_error (G_STRLOC ": handler block_count overflow, %s", REPORT_BUG); 1066#endif 1067 1068 handler->block_count += 1; 1069 } 1070 else 1071 g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id); 1072 G_UNLOCK (g_signal_mutex); 1073} 1074 1075void 1076g_signal_handler_unblock (gpointer instance, 1077 guint handler_id) 1078{ 1079 Handler *handler; 1080 1081 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 1082 g_return_if_fail (handler_id > 0); 1083 1084 G_LOCK (g_signal_mutex); 1085 handler = handler_lookup (instance, handler_id, NULL); 1086 if (handler) 1087 { 1088 if (handler->block_count) 1089 handler->block_count -= 1; 1090 else 1091 g_warning (G_STRLOC ": handler `%u' of instance `%p' is not blocked", handler_id, instance); 1092 } 1093 else 1094 g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id); 1095 G_UNLOCK (g_signal_mutex); 1096} 1097 1098void 1099g_signal_handler_disconnect (gpointer instance, 1100 guint handler_id) 1101{ 1102 Handler *handler; 1103 guint signal_id; 1104 1105 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 1106 g_return_if_fail (handler_id > 0); 1107 1108 G_LOCK (g_signal_mutex); 1109 handler = handler_lookup (instance, handler_id, &signal_id); 1110 if (handler) 1111 { 1112 handler->id = 0; 1113 handler->block_count = 1; 1114 handler_unref_R (signal_id, instance, handler); 1115 } 1116 else 1117 g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id); 1118 G_UNLOCK (g_signal_mutex); 1119} 1120 1121void 1122g_signal_handlers_destroy (gpointer instance) 1123{ 1124 GBSearchArray *hlbsa; 1125 1126 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 1127 1128 G_LOCK (g_signal_mutex); 1129 hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance); 1130 if (hlbsa) 1131 { 1132 guint i; 1133 1134 /* reentrancy caution, delete instance trace first */ 1135 g_hash_table_remove (g_handler_list_bsa_ht, instance); 1136 1137 for (i = 0; i < hlbsa->n_nodes; i++) 1138 { 1139 HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i); 1140 Handler *handler = hlist->handlers; 1141 1142 while (handler) 1143 { 1144 Handler *tmp = handler; 1145 1146 handler = tmp->next; 1147 tmp->block_count = 1; 1148 /* cruel unlink, this works because _all_ handlers vanish */ 1149 tmp->next = NULL; 1150 tmp->prev = tmp; 1151 if (tmp->id) 1152 { 1153 tmp->id = 0; 1154 handler_unref_R (0, NULL, tmp); 1155 } 1156 } 1157 } 1158 g_free (hlbsa->nodes); 1159 g_generic_node_free (&g_bsa_ts, hlbsa); 1160 } 1161 G_UNLOCK (g_signal_mutex); 1162} 1163 1164guint 1165g_signal_handler_find (gpointer instance, 1166 GSignalMatchType mask, 1167 guint signal_id, 1168 GQuark detail, 1169 GClosure *closure, 1170 gpointer func, 1171 gpointer data) 1172{ 1173 guint handler_id = 0; 1174 1175 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); 1176 g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0); 1177 1178 if (mask & G_SIGNAL_MATCH_MASK) 1179 { 1180 HandlerMatch *mlist; 1181 1182 G_LOCK (g_signal_mutex); 1183 mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, TRUE); 1184 if (mlist) 1185 { 1186 handler_id = mlist->handler->id; 1187 handler_match_free1_R (mlist, instance); 1188 } 1189 G_UNLOCK (g_signal_mutex); 1190 } 1191 1192 return handler_id; 1193} 1194 1195static guint 1196signal_handlers_foreach_matched_R (gpointer instance, 1197 GSignalMatchType mask, 1198 guint signal_id, 1199 GQuark detail, 1200 GClosure *closure, 1201 gpointer func, 1202 gpointer data, 1203 void (*callback) (gpointer instance, 1204 guint handler_id)) 1205{ 1206 HandlerMatch *mlist; 1207 guint n_handlers = 0; 1208 1209 mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, FALSE); 1210 while (mlist) 1211 { 1212 n_handlers++; 1213 G_UNLOCK (g_signal_mutex); 1214 callback (instance, mlist->handler->id); 1215 G_LOCK (g_signal_mutex); 1216 mlist = handler_match_free1_R (mlist, instance); 1217 } 1218 1219 return n_handlers; 1220} 1221 1222guint 1223g_signal_handlers_block_matched (gpointer instance, 1224 GSignalMatchType mask, 1225 guint signal_id, 1226 GQuark detail, 1227 GClosure *closure, 1228 gpointer func, 1229 gpointer data) 1230{ 1231 guint n_handlers = 0; 1232 1233 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE); 1234 g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE); 1235 1236 if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) 1237 { 1238 G_LOCK (g_signal_mutex); 1239 n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail, 1240 closure, func, data, 1241 g_signal_handler_block); 1242 G_UNLOCK (g_signal_mutex); 1243 } 1244 1245 return n_handlers; 1246} 1247 1248guint 1249g_signal_handlers_unblock_matched (gpointer instance, 1250 GSignalMatchType mask, 1251 guint signal_id, 1252 GQuark detail, 1253 GClosure *closure, 1254 gpointer func, 1255 gpointer data) 1256{ 1257 guint n_handlers = 0; 1258 1259 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE); 1260 g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE); 1261 1262 if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) 1263 { 1264 G_LOCK (g_signal_mutex); 1265 n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail, 1266 closure, func, data, 1267 g_signal_handler_unblock); 1268 G_UNLOCK (g_signal_mutex); 1269 } 1270 1271 return n_handlers; 1272} 1273 1274guint 1275g_signal_handlers_disconnect_matched (gpointer instance, 1276 GSignalMatchType mask, 1277 guint signal_id, 1278 GQuark detail, 1279 GClosure *closure, 1280 gpointer func, 1281 gpointer data) 1282{ 1283 guint n_handlers = 0; 1284 1285 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE); 1286 g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE); 1287 1288 if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) 1289 { 1290 G_LOCK (g_signal_mutex); 1291 n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail, 1292 closure, func, data, 1293 g_signal_handler_disconnect); 1294 G_UNLOCK (g_signal_mutex); 1295 } 1296 1297 return n_handlers; 1298} 1299 1300gboolean 1301g_signal_has_handler_pending (gpointer instance, 1302 guint signal_id, 1303 GQuark detail, 1304 gboolean may_be_blocked) 1305{ 1306 HandlerMatch *mlist; 1307 gboolean has_pending; 1308 1309 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE); 1310 g_return_val_if_fail (signal_id > 0, FALSE); 1311 1312 G_LOCK (g_signal_mutex); 1313 if (detail) 1314 { 1315 SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id); 1316 1317 if (!(node->flags & G_SIGNAL_DETAILED)) 1318 { 1319 g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); 1320 G_UNLOCK (g_signal_mutex); 1321 return FALSE; 1322 } 1323 } 1324 mlist = handlers_find (instance, 1325 (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | (may_be_blocked ? 0 : G_SIGNAL_MATCH_UNBLOCKED)), 1326 signal_id, detail, NULL, NULL, NULL, TRUE); 1327 if (mlist) 1328 { 1329 has_pending = TRUE; 1330 handler_match_free1_R (mlist, instance); 1331 } 1332 else 1333 has_pending = FALSE; 1334 G_UNLOCK (g_signal_mutex); 1335 1336 return has_pending; 1337} 1338 1339void 1340g_signal_emitv (const GValue *instance_and_params, 1341 guint signal_id, 1342 GQuark detail, 1343 GValue *return_value) 1344{ 1345 SignalNode *node; 1346 gpointer instance; 1347 const GValue *param_values; 1348 guint i; 1349 1350 g_return_if_fail (instance_and_params != NULL); 1351 instance = g_value_get_as_pointer (instance_and_params); 1352 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 1353 g_return_if_fail (signal_id > 0); 1354 1355 param_values = instance_and_params + 1; 1356 1357 G_LOCK (g_signal_mutex); 1358 node = LOOKUP_SIGNAL_NODE (signal_id); 1359#ifndef G_DISABLE_CHECKS 1360 if (!node || !g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype)) 1361 { 1362 g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance); 1363 G_UNLOCK (g_signal_mutex); 1364 return; 1365 } 1366 if (detail && !(node->flags & G_SIGNAL_DETAILED)) 1367 { 1368 g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); 1369 G_UNLOCK (g_signal_mutex); 1370 return; 1371 } 1372 for (i = 0; i < node->n_params; i++) 1373 if (!G_VALUE_HOLDS (param_values + i, node->param_types[i])) 1374 { 1375 g_critical (G_STRLOC ": value for `%s' parameter %u for signal \"%s\" is of type `%s'", 1376 g_type_name (node->param_types[i]), 1377 i, 1378 node->name, 1379 G_VALUE_TYPE_NAME (param_values + i)); 1380 G_UNLOCK (g_signal_mutex); 1381 return; 1382 } 1383 if (node->return_type != G_TYPE_NONE) 1384 { 1385 if (!return_value) 1386 { 1387 g_critical (G_STRLOC ": return value `%s' for signal \"%s\" is (NULL)", 1388 g_type_name (node->return_type), 1389 node->name); 1390 G_UNLOCK (g_signal_mutex); 1391 return; 1392 } 1393 else if (!node->accumulator && !G_VALUE_HOLDS (return_value, node->return_type)) 1394 { 1395 g_critical (G_STRLOC ": return value `%s' for signal \"%s\" is of type `%s'", 1396 g_type_name (node->return_type), 1397 node->name, 1398 G_VALUE_TYPE_NAME (return_value)); 1399 G_UNLOCK (g_signal_mutex); 1400 return; 1401 } 1402 } 1403 else 1404 return_value = NULL; 1405#endif /* !G_DISABLE_CHECKS */ 1406 1407 signal_emit_R (node, detail, instance, return_value, instance_and_params); 1408 1409 G_UNLOCK (g_signal_mutex); 1410} 1411 1412static void 1413signal_emit_R (SignalNode *node, 1414 GQuark detail, 1415 gpointer instance, 1416 GValue *return_value, 1417 const GValue *instance_and_params) 1418{ 1419 EmissionState emission_state = 0; 1420 GSignalAccumulator accumulator; 1421 GSignalInvocationHint ihint; 1422 GClosure *class_closure; 1423 HandlerList *hlist; 1424 Handler *handler_list = NULL; 1425 GValue accu; 1426 gboolean accu_used = FALSE; 1427 guint signal_id = node->signal_id; 1428 1429 if (node->flags & G_SIGNAL_NO_RECURSE) 1430 { 1431 Emission *emission = emission_find (g_restart_emissions, signal_id, detail, instance); 1432 1433 if (emission) 1434 { 1435 *emission->state_p = EMISSION_RESTART; 1436 return; 1437 } 1438 } 1439 ihint.signal_id = node->signal_id; 1440 ihint.detail = detail; 1441 accumulator = node->accumulator; 1442 if (accumulator) 1443 { 1444 G_UNLOCK (g_signal_mutex); 1445 g_value_init (&accu, node->return_type); 1446 G_LOCK (g_signal_mutex); 1447 } 1448 emission_push ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, 1449 signal_id, detail, instance, &emission_state); 1450 class_closure = node->class_closure; 1451 1452 EMIT_RESTART: 1453 1454 if (handler_list) 1455 handler_unref_R (signal_id, instance, handler_list); 1456 hlist = handler_list_lookup (signal_id, instance); 1457 handler_list = hlist ? hlist->handlers : NULL; 1458 if (handler_list) 1459 handler_ref (handler_list); 1460 1461 ihint.run_type = G_SIGNAL_RUN_FIRST; 1462 1463 if ((node->flags & G_SIGNAL_RUN_FIRST) && class_closure) 1464 { 1465 emission_state = EMISSION_RUN; 1466 1467 G_UNLOCK (g_signal_mutex); 1468 if (accumulator) 1469 { 1470 if (accu_used) 1471 g_value_reset (&accu); 1472 g_closure_invoke (class_closure, 1473 &accu, 1474 node->n_params + 1, 1475 instance_and_params, 1476 &ihint); 1477 if (!accumulator (&ihint, return_value, &accu) && 1478 emission_state == EMISSION_RUN) 1479 emission_state = EMISSION_STOP; 1480 accu_used = TRUE; 1481 } 1482 else 1483 g_closure_invoke (class_closure, 1484 return_value, 1485 node->n_params + 1, 1486 instance_and_params, 1487 &ihint); 1488 G_LOCK (g_signal_mutex); 1489 1490 if (emission_state == EMISSION_STOP) 1491 goto EMIT_CLEANUP; 1492 else if (emission_state == EMISSION_RESTART) 1493 goto EMIT_RESTART; 1494 } 1495 1496 if (node->emission_hooks) 1497 { 1498 emission_state = EMISSION_HOOK; 1499 1500 G_UNLOCK (g_signal_mutex); 1501 g_print ("emission_hooks()\n"); 1502 G_LOCK (g_signal_mutex); 1503 1504 if (emission_state == EMISSION_RESTART) 1505 goto EMIT_RESTART; 1506 } 1507 1508 if (handler_list) 1509 { 1510 Handler *handler = handler_list; 1511 1512 emission_state = EMISSION_RUN; 1513 handler_ref (handler); 1514 do 1515 { 1516 Handler *tmp; 1517 1518 if (handler->after) 1519 { 1520 handler_unref_R (signal_id, instance, handler_list); 1521 handler_list = handler; 1522 break; 1523 } 1524 else if (!handler->block_count && (!handler->detail || handler->detail == detail)) 1525 { 1526 G_UNLOCK (g_signal_mutex); 1527 if (accumulator) 1528 { 1529 if (accu_used) 1530 g_value_reset (&accu); 1531 g_closure_invoke (handler->closure, 1532 &accu, 1533 node->n_params + 1, 1534 instance_and_params, 1535 &ihint); 1536 if (!accumulator (&ihint, return_value, &accu) && 1537 emission_state == EMISSION_RUN) 1538 emission_state = EMISSION_STOP; 1539 accu_used = TRUE; 1540 } 1541 else 1542 g_closure_invoke (handler->closure, 1543 return_value, 1544 node->n_params + 1, 1545 instance_and_params, 1546 &ihint); 1547 G_LOCK (g_signal_mutex); 1548 1549 tmp = emission_state == EMISSION_RUN ? handler->next : NULL; 1550 } 1551 else 1552 tmp = handler->next; 1553 1554 if (tmp) 1555 handler_ref (tmp); 1556 handler_unref_R (signal_id, instance, handler_list); 1557 handler_list = handler; 1558 handler = tmp; 1559 } 1560 while (handler); 1561 1562 if (emission_state == EMISSION_STOP) 1563 goto EMIT_CLEANUP; 1564 else if (emission_state == EMISSION_RESTART) 1565 goto EMIT_RESTART; 1566 } 1567 1568 ihint.run_type = G_SIGNAL_RUN_LAST; 1569 1570 if ((node->flags & G_SIGNAL_RUN_LAST) && class_closure) 1571 { 1572 emission_state = EMISSION_RUN; 1573 1574 G_UNLOCK (g_signal_mutex); 1575 if (accumulator) 1576 { 1577 if (accu_used) 1578 g_value_reset (&accu); 1579 g_closure_invoke (class_closure, 1580 &accu, 1581 node->n_params + 1, 1582 instance_and_params, 1583 &ihint); 1584 if (!accumulator (&ihint, return_value, &accu) && 1585 emission_state == EMISSION_RUN) 1586 emission_state = EMISSION_STOP; 1587 accu_used = TRUE; 1588 } 1589 else 1590 g_closure_invoke (class_closure, 1591 return_value, 1592 node->n_params + 1, 1593 instance_and_params, 1594 &ihint); 1595 G_LOCK (g_signal_mutex); 1596 1597 if (emission_state == EMISSION_STOP) 1598 goto EMIT_CLEANUP; 1599 else if (emission_state == EMISSION_RESTART) 1600 goto EMIT_RESTART; 1601 } 1602 1603 if (handler_list) 1604 { 1605 Handler *handler = handler_list; 1606 1607 emission_state = EMISSION_RUN; 1608 handler_ref (handler); 1609 do 1610 { 1611 Handler *tmp; 1612 1613 if (handler->after && !handler->block_count && (!handler->detail || handler->detail == detail)) 1614 { 1615 G_UNLOCK (g_signal_mutex); 1616 if (accumulator) 1617 { 1618 if (accu_used) 1619 g_value_reset (&accu); 1620 g_closure_invoke (handler->closure, 1621 &accu, 1622 node->n_params + 1, 1623 instance_and_params, 1624 &ihint); 1625 if (!accumulator (&ihint, return_value, &accu) && 1626 emission_state == EMISSION_RUN) 1627 emission_state = EMISSION_STOP; 1628 accu_used = TRUE; 1629 } 1630 else 1631 g_closure_invoke (handler->closure, 1632 return_value, 1633 node->n_params + 1, 1634 instance_and_params, 1635 &ihint); 1636 G_LOCK (g_signal_mutex); 1637 1638 tmp = emission_state == EMISSION_RUN ? handler->next : NULL; 1639 } 1640 else 1641 tmp = handler->next; 1642 1643 if (tmp) 1644 handler_ref (tmp); 1645 handler_unref_R (signal_id, instance, handler); 1646 handler = tmp; 1647 } 1648 while (handler); 1649 1650 if (emission_state == EMISSION_STOP) 1651 goto EMIT_CLEANUP; 1652 else if (emission_state == EMISSION_RESTART) 1653 goto EMIT_RESTART; 1654 } 1655 1656 EMIT_CLEANUP: 1657 1658 ihint.run_type = G_SIGNAL_RUN_CLEANUP; 1659 1660 if ((node->flags & G_SIGNAL_RUN_CLEANUP) && class_closure) 1661 { 1662 gboolean need_unset = FALSE; 1663 1664 emission_state = EMISSION_STOP; 1665 1666 G_UNLOCK (g_signal_mutex); 1667 if (node->return_type != G_TYPE_NONE) 1668 { 1669 if (!accumulator) 1670 { 1671 g_value_init (&accu, node->return_type); 1672 need_unset = TRUE; 1673 } 1674 else if (accu_used) 1675 g_value_reset (&accu); 1676 } 1677 g_closure_invoke (class_closure, 1678 node->return_type != G_TYPE_NONE ? &accu : NULL, 1679 node->n_params + 1, 1680 instance_and_params, 1681 &ihint); 1682 if (need_unset) 1683 g_value_unset (&accu); 1684 G_LOCK (g_signal_mutex); 1685 1686 if (emission_state == EMISSION_RESTART) 1687 goto EMIT_RESTART; 1688 } 1689 1690 if (handler_list) 1691 handler_unref_R (signal_id, instance, handler_list); 1692 1693 emission_pop ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, &emission_state); 1694 if (accumulator) 1695 { 1696 G_UNLOCK (g_signal_mutex); 1697 g_value_unset (&accu); 1698 G_LOCK (g_signal_mutex); 1699 } 1700} 1701