#include <config.h>
#include "gsignal.h"
+
#include "gbsearcharray.h"
#include "gvaluecollector.h"
#include "gvaluetypes.h"
#include "gboxed.h"
+#include "gobject.h"
+#include "genums.h"
+
+#include "gobjectalias.h"
+
#include <string.h>
#include <signal.h>
/* pre allocation configurations
*/
#define MAX_STACK_VALUES (16)
-#define HANDLER_PRE_ALLOC (48)
-#define REPORT_BUG "please report occourance circumstances to gtk-devel-list@gnome.org"
+#define REPORT_BUG "please report occurrence circumstances to gtk-devel-list@gnome.org"
#ifdef G_ENABLE_DEBUG
#define IF_DEBUG(debug_type, cond) if ((_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type) || cond)
static volatile gpointer g_trace_instance_signals = NULL;
#endif /* G_ENABLE_DEBUG */
-/* --- generic allocation --- */
-/* we special case allocations generically by replacing
- * these functions with more speed/memory aware variants
- */
-#ifndef DISABLE_MEM_POOLS
-static inline gpointer
-g_generic_node_alloc (GTrashStack **trash_stack_p,
- guint sizeof_node,
- guint nodes_pre_alloc)
-{
- gpointer node = g_trash_stack_pop (trash_stack_p);
-
- if (!node)
- {
- guint8 *block;
-
- nodes_pre_alloc = MAX (nodes_pre_alloc, 1);
- block = g_malloc (sizeof_node * nodes_pre_alloc);
- while (--nodes_pre_alloc)
- {
- g_trash_stack_push (trash_stack_p, block);
- block += sizeof_node;
- }
- node = block;
- }
-
- return node;
-}
-#define g_generic_node_free(trash_stack_p, node) g_trash_stack_push (trash_stack_p, node)
-#else /* !DISABLE_MEM_POOLS */
-#define g_generic_node_alloc(t,sizeof_node,p) g_malloc (sizeof_node)
-#define g_generic_node_free(t,node) g_free (node)
-#endif /* !DISABLE_MEM_POOLS */
-
-
/* --- typedefs --- */
typedef struct _SignalNode SignalNode;
typedef struct _SignalKey SignalKey;
/* permanent portion */
guint signal_id;
GType itype;
- gchar *name;
+ const gchar *name;
guint destroyed : 1;
/* reinitializable portion */
{
guint signal_id;
Handler *handlers;
+ Handler *tail_before; /* normal signal handlers are appended here */
+ Handler *tail_after; /* CONNECT_AFTER handlers are appended here */
};
+
struct _Handler
{
gulong sequential_number;
Handler *next;
Handler *prev;
GQuark detail;
- guint ref_count : 16;
-#define HANDLER_MAX_REF_COUNT (1 << 16)
- guint block_count : 12;
-#define HANDLER_MAX_BLOCK_COUNT (1 << 12)
+ guint ref_count;
+ guint block_count : 16;
+#define HANDLER_MAX_BLOCK_COUNT (1 << 16)
guint after : 1;
GClosure *closure;
};
{
Handler *handler;
HandlerMatch *next;
- union {
- guint signal_id;
- gpointer dummy;
- } d;
+ guint signal_id;
};
typedef struct
static GHashTable *g_handler_list_bsa_ht = NULL;
static Emission *g_recursive_emissions = NULL;
static Emission *g_restart_emissions = NULL;
-#ifndef DISABLE_MEM_POOLS
-static GTrashStack *g_handler_ts = NULL;
-#endif
static gulong g_handler_sequential_number = 1;
G_LOCK_DEFINE_STATIC (g_signal_mutex);
#define SIGNAL_LOCK() G_LOCK (g_signal_mutex)
key.quark = quark;
- /* try looking up signals for this type and its anchestors */
+ /* try looking up signals for this type and its ancestors */
do
{
SignalKey *signal_key;
HandlerList key;
key.signal_id = signal_id;
- key.handlers = NULL;
+ key.handlers = NULL;
+ key.tail_before = NULL;
+ key.tail_after = NULL;
if (!hlbsa)
{
hlbsa = g_bsearch_array_create (&g_signal_hlbsa_bconfig);
{
HandlerMatch *node;
- /* yeah, we could use our own memchunk here, introducing yet more
- * rarely used cached nodes and extra allocation overhead.
- * instead, we use GList* nodes, since they are exactly the size
- * we need and are already cached. g_signal_init() asserts this.
- */
- node = (HandlerMatch*) g_list_alloc ();
+ node = g_slice_new (HandlerMatch);
node->handler = handler;
node->next = list;
- node->d.signal_id = signal_id;
+ node->signal_id = signal_id;
handler_ref (handler);
return node;
{
HandlerMatch *next = node->next;
- handler_unref_R (node->d.signal_id, instance, node->handler);
- g_list_free_1 ((GList*) node);
+ handler_unref_R (node->signal_id, instance, node->handler);
+ g_slice_free (HandlerMatch, node);
return next;
}
static inline Handler*
handler_new (gboolean after)
{
- Handler *handler = g_generic_node_alloc (&g_handler_ts,
- sizeof (Handler),
- HANDLER_PRE_ALLOC);
+ Handler *handler = g_slice_new (Handler);
#ifndef G_DISABLE_CHECKS
if (g_handler_sequential_number < 1)
g_error (G_STRLOC ": handler id overflow, %s", REPORT_BUG);
{
g_return_if_fail (handler->ref_count > 0);
-#ifndef G_DISABLE_CHECKS
- if (handler->ref_count >= HANDLER_MAX_REF_COUNT - 1)
- g_error (G_STRLOC ": handler ref_count overflow, %s", REPORT_BUG);
-#endif
-
- handler->ref_count += 1;
+ g_atomic_int_inc (&handler->ref_count);
}
static inline void
gpointer instance,
Handler *handler)
{
+ gboolean is_zero;
+
g_return_if_fail (handler->ref_count > 0);
- handler->ref_count -= 1;
- if (!handler->ref_count)
+ is_zero = g_atomic_int_dec_and_test (&handler->ref_count);
+
+ if (G_UNLIKELY (is_zero))
{
+ HandlerList *hlist = NULL;
+
if (handler->next)
handler->next->prev = handler->prev;
- if (handler->prev) /* watch out for g_signal_handlers_destroy()! */
+ if (handler->prev) /* watch out for g_signal_handlers_destroy()! */
handler->prev->next = handler->next;
else
{
- HandlerList *hlist = handler_list_lookup (signal_id, instance);
-
+ hlist = handler_list_lookup (signal_id, instance);
hlist->handlers = handler->next;
}
+
+ if (instance)
+ {
+ /* check if we are removing the handler pointed to by tail_before */
+ if (!handler->after && (!handler->next || handler->next->after))
+ {
+ if (!hlist)
+ hlist = handler_list_lookup (signal_id, instance);
+ if (hlist)
+ {
+ g_assert (hlist->tail_before == handler); /* paranoid */
+ hlist->tail_before = handler->prev;
+ }
+ }
+
+ /* check if we are removing the handler pointed to by tail_after */
+ if (!handler->next)
+ {
+ if (!hlist)
+ hlist = handler_list_lookup (signal_id, instance);
+ if (hlist)
+ {
+ g_assert (hlist->tail_after == handler); /* paranoid */
+ hlist->tail_after = handler->prev;
+ }
+ }
+ }
+
SIGNAL_UNLOCK ();
g_closure_unref (handler->closure);
SIGNAL_LOCK ();
- g_generic_node_free (&g_handler_ts, handler);
+ g_slice_free (Handler, handler);
}
}
hlist = handler_list_ensure (signal_id, instance);
if (!hlist->handlers)
- hlist->handlers = handler;
- else if (hlist->handlers->after && !handler->after)
{
- handler->next = hlist->handlers;
- hlist->handlers->prev = handler;
hlist->handlers = handler;
+ if (!handler->after)
+ hlist->tail_before = handler;
+ }
+ else if (handler->after)
+ {
+ handler->prev = hlist->tail_after;
+ hlist->tail_after->next = handler;
}
else
{
- Handler *tmp = hlist->handlers;
-
- if (handler->after)
- while (tmp->next)
- tmp = tmp->next;
- else
- while (tmp->next && !tmp->next->after)
- tmp = tmp->next;
- if (tmp->next)
- tmp->next->prev = handler;
- handler->next = tmp->next;
- handler->prev = tmp;
- tmp->next = handler;
+ if (hlist->tail_before)
+ {
+ handler->next = hlist->tail_before->next;
+ if (handler->next)
+ handler->next->prev = handler;
+ handler->prev = hlist->tail_before;
+ hlist->tail_before->next = handler;
+ }
+ else /* insert !after handler into a list of only after handlers */
+ {
+ handler->next = hlist->handlers;
+ if (handler->next)
+ handler->next->prev = handler;
+ hlist->handlers = handler;
+ }
+ hlist->tail_before = handler;
}
+
+ if (!handler->next)
+ hlist->tail_after = handler;
}
static inline void
}
void
-g_signal_init (void) /* sync with gtype.c */
+g_signal_init (void)
{
SIGNAL_LOCK ();
if (!g_n_signal_nodes)
{
- /* handler_id_node_prepend() requires this */
- g_assert (sizeof (GList) == sizeof (HandlerMatch));
-
/* setup handler list binary searchable array hash table (in german, that'd be one word ;) */
g_handler_list_bsa_ht = g_hash_table_new (g_direct_hash, NULL);
g_signal_key_bsa = g_bsearch_array_create (&g_signal_key_bconfig);
SIGNAL_LOCK ();
node = LOOKUP_SIGNAL_NODE (signal_id);
- if (!node || node->destroyed || (node->flags & G_SIGNAL_NO_HOOKS))
+ if (!node || node->destroyed)
{
g_warning ("%s: invalid signal id `%u'", G_STRLOC, signal_id);
SIGNAL_UNLOCK ();
return 0;
}
+ if (node->flags & G_SIGNAL_NO_HOOKS)
+ {
+ g_warning ("%s: signal id `%u' does not support emission hooks (G_SIGNAL_NO_HOOKS flag set)", G_STRLOC, signal_id);
+ SIGNAL_UNLOCK ();
+ return 0;
+ }
if (detail && !(node->flags & G_SIGNAL_DETAILED))
{
g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
g_signal_name (guint signal_id)
{
SignalNode *node;
- gchar *name;
+ const gchar *name;
SIGNAL_LOCK ();
node = LOOKUP_SIGNAL_NODE (signal_id);
name = node ? node->name : NULL;
SIGNAL_UNLOCK ();
- return name;
+ return (char*) name;
}
void
key.quark = g_quark_from_string (node->name);
key.signal_id = signal_id;
g_signal_key_bsa = g_bsearch_array_insert (g_signal_key_bsa, &g_signal_key_bconfig, &key);
- g_strdelimit (node->name, "_", '-');
- key.quark = g_quark_from_static_string (node->name);
+ g_strdelimit (name, "_", '-');
+ node->name = g_intern_string (name);
+ key.quark = g_quark_from_string (name);
g_signal_key_bsa = g_bsearch_array_insert (g_signal_key_bsa, &g_signal_key_bconfig, &key);
}
node->destroyed = FALSE;
}
SIGNAL_UNLOCK ();
+ g_free (name);
+
return signal_id;
}
gboolean connected;
g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
- g_return_val_if_fail (handler_id > 0, FALSE);
SIGNAL_LOCK ();
handler = handler_lookup (instance, handler_id, NULL);
GQuark detail,
GValue *return_value)
{
- const GValue *param_values;
gpointer instance;
SignalNode *node;
#ifdef G_ENABLE_DEBUG
+ const GValue *param_values;
guint i;
#endif
g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
g_return_if_fail (signal_id > 0);
+#ifdef G_ENABLE_DEBUG
param_values = instance_and_params + 1;
-
+#endif
+
SIGNAL_LOCK ();
node = LOOKUP_SIGNAL_NODE (signal_id);
if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
g_free (error);
/* we purposely leak the value here, it might not be
- * in a sane state if an error condition occoured
+ * in a sane state if an error condition occured
*/
}
}
return "<invalid>";
}
+gboolean
+g_signal_accumulator_true_handled (GSignalInvocationHint *ihint,
+ GValue *return_accu,
+ const GValue *handler_return,
+ gpointer dummy)
+{
+ gboolean continue_emission;
+ gboolean signal_handled;
+
+ signal_handled = g_value_get_boolean (handler_return);
+ g_value_set_boolean (return_accu, signal_handled);
+ continue_emission = !signal_handled;
+
+ return continue_emission;
+}
+
/* --- compile standard marshallers --- */
-#include "gobject.h"
-#include "genums.h"
#include "gmarshal.c"
+
+#define __G_SIGNAL_C__
+#include "gobjectaliasdef.c"