summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Janik <timj@gtk.org>2001-03-08 16:34:59 +0000
committerTim Janik <timj@src.gnome.org>2001-03-08 16:34:59 +0000
commit617332234d4426ed0941ec1e2cb9f0736bd796c3 (patch)
tree096311062437edd7f702200e6d8b1f9486f6dcad
parentc811ed93d3e7b64b3fcf5aab7ac405e0a8d36a59 (diff)
destruction cleanup. there's one ->finalize_hook member in the hooklist
Thu Mar 8 16:23:34 2001 Tim Janik <timj@gtk.org> * ghook.[hc]: destruction cleanup. there's one ->finalize_hook member in the hooklist now that gets called when a hook should be destroyed, that's it. that function is guarranteed to be called only when all ref_counts to the hook vanished, thus also when the hook is not in call. Thu Mar 8 16:35:48 2001 Tim Janik <timj@gtk.org> * gparamspecs.[hc]: s/g_param_spec_string_c/g_param_spec_stringc/. * gsignal.[hc]: fixed accumulator invocation, implemented emission hooks. and no, neither of these callbacks are called via a closure, language bindings can wrap the accumulator and emission hook interface, they already get parameters marshalled into a GValue array. (g_signal_connect): removed this function as its C specific, doesn't cover the swapped argument, is too close to its broken original gtk_signal_connect() and creates demand for _swapped, _after and _swapped_after variants <brrr>. (g_signal_connectc): convenience macro to connect a C handler func with data, like the old g_signal_connect() plus swapped argument. * gtype.h: * gboxed.c: added G_TYPE_VALUE boxed type.
-rw-r--r--ChangeLog9
-rw-r--r--ChangeLog.pre-2-09
-rw-r--r--ChangeLog.pre-2-109
-rw-r--r--ChangeLog.pre-2-129
-rw-r--r--ChangeLog.pre-2-29
-rw-r--r--ChangeLog.pre-2-49
-rw-r--r--ChangeLog.pre-2-69
-rw-r--r--ChangeLog.pre-2-89
-rw-r--r--docs/reference/glib/tmpl/glib-unused.sgml14
-rw-r--r--docs/reference/glib/tmpl/hooks.sgml29
-rw-r--r--docs/reference/glib/tmpl/macros_misc.sgml1
-rw-r--r--docs/reference/gobject/tmpl/gobject-unused.sgml21
-rw-r--r--docs/reference/gobject/tmpl/signals.sgml19
-rw-r--r--docs/reference/gobject/tmpl/standard_params.sgml13
-rw-r--r--docs/reference/gobject/tmpl/types.sgml1
-rw-r--r--ghook.c44
-rw-r--r--ghook.h66
-rw-r--r--glib/ghook.c44
-rw-r--r--glib/ghook.h66
-rw-r--r--gobject/ChangeLog19
-rw-r--r--gobject/gboxed.c33
-rw-r--r--gobject/gobject.c6
-rw-r--r--gobject/gparamspecs.c10
-rw-r--r--gobject/gparamspecs.h2
-rw-r--r--gobject/gsignal.c300
-rw-r--r--gobject/gsignal.h48
-rw-r--r--gobject/gtype.h3
27 files changed, 525 insertions, 286 deletions
diff --git a/ChangeLog b/ChangeLog
index 65bc175b7..f7367cb5e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Thu Mar 8 16:23:34 2001 Tim Janik <timj@gtk.org>
+
+ * ghook.[hc]: destruction cleanup. there's one
+ ->finalize_hook member in the hooklist now that gets
+ called when a hook should be destroyed, that's it.
+ that function is guarranteed to be called only when
+ all ref_counts to the hook vanished, thus also when
+ the hook is not in call.
+
2001-03-08 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* configure.in (FLAG_DOES_NOT_WORK): Fix typo and thus bug #51862.
diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0
index 65bc175b7..f7367cb5e 100644
--- a/ChangeLog.pre-2-0
+++ b/ChangeLog.pre-2-0
@@ -1,3 +1,12 @@
+Thu Mar 8 16:23:34 2001 Tim Janik <timj@gtk.org>
+
+ * ghook.[hc]: destruction cleanup. there's one
+ ->finalize_hook member in the hooklist now that gets
+ called when a hook should be destroyed, that's it.
+ that function is guarranteed to be called only when
+ all ref_counts to the hook vanished, thus also when
+ the hook is not in call.
+
2001-03-08 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* configure.in (FLAG_DOES_NOT_WORK): Fix typo and thus bug #51862.
diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10
index 65bc175b7..f7367cb5e 100644
--- a/ChangeLog.pre-2-10
+++ b/ChangeLog.pre-2-10
@@ -1,3 +1,12 @@
+Thu Mar 8 16:23:34 2001 Tim Janik <timj@gtk.org>
+
+ * ghook.[hc]: destruction cleanup. there's one
+ ->finalize_hook member in the hooklist now that gets
+ called when a hook should be destroyed, that's it.
+ that function is guarranteed to be called only when
+ all ref_counts to the hook vanished, thus also when
+ the hook is not in call.
+
2001-03-08 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* configure.in (FLAG_DOES_NOT_WORK): Fix typo and thus bug #51862.
diff --git a/ChangeLog.pre-2-12 b/ChangeLog.pre-2-12
index 65bc175b7..f7367cb5e 100644
--- a/ChangeLog.pre-2-12
+++ b/ChangeLog.pre-2-12
@@ -1,3 +1,12 @@
+Thu Mar 8 16:23:34 2001 Tim Janik <timj@gtk.org>
+
+ * ghook.[hc]: destruction cleanup. there's one
+ ->finalize_hook member in the hooklist now that gets
+ called when a hook should be destroyed, that's it.
+ that function is guarranteed to be called only when
+ all ref_counts to the hook vanished, thus also when
+ the hook is not in call.
+
2001-03-08 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* configure.in (FLAG_DOES_NOT_WORK): Fix typo and thus bug #51862.
diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2
index 65bc175b7..f7367cb5e 100644
--- a/ChangeLog.pre-2-2
+++ b/ChangeLog.pre-2-2
@@ -1,3 +1,12 @@
+Thu Mar 8 16:23:34 2001 Tim Janik <timj@gtk.org>
+
+ * ghook.[hc]: destruction cleanup. there's one
+ ->finalize_hook member in the hooklist now that gets
+ called when a hook should be destroyed, that's it.
+ that function is guarranteed to be called only when
+ all ref_counts to the hook vanished, thus also when
+ the hook is not in call.
+
2001-03-08 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* configure.in (FLAG_DOES_NOT_WORK): Fix typo and thus bug #51862.
diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4
index 65bc175b7..f7367cb5e 100644
--- a/ChangeLog.pre-2-4
+++ b/ChangeLog.pre-2-4
@@ -1,3 +1,12 @@
+Thu Mar 8 16:23:34 2001 Tim Janik <timj@gtk.org>
+
+ * ghook.[hc]: destruction cleanup. there's one
+ ->finalize_hook member in the hooklist now that gets
+ called when a hook should be destroyed, that's it.
+ that function is guarranteed to be called only when
+ all ref_counts to the hook vanished, thus also when
+ the hook is not in call.
+
2001-03-08 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* configure.in (FLAG_DOES_NOT_WORK): Fix typo and thus bug #51862.
diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6
index 65bc175b7..f7367cb5e 100644
--- a/ChangeLog.pre-2-6
+++ b/ChangeLog.pre-2-6
@@ -1,3 +1,12 @@
+Thu Mar 8 16:23:34 2001 Tim Janik <timj@gtk.org>
+
+ * ghook.[hc]: destruction cleanup. there's one
+ ->finalize_hook member in the hooklist now that gets
+ called when a hook should be destroyed, that's it.
+ that function is guarranteed to be called only when
+ all ref_counts to the hook vanished, thus also when
+ the hook is not in call.
+
2001-03-08 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* configure.in (FLAG_DOES_NOT_WORK): Fix typo and thus bug #51862.
diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8
index 65bc175b7..f7367cb5e 100644
--- a/ChangeLog.pre-2-8
+++ b/ChangeLog.pre-2-8
@@ -1,3 +1,12 @@
+Thu Mar 8 16:23:34 2001 Tim Janik <timj@gtk.org>
+
+ * ghook.[hc]: destruction cleanup. there's one
+ ->finalize_hook member in the hooklist now that gets
+ called when a hook should be destroyed, that's it.
+ that function is guarranteed to be called only when
+ all ref_counts to the hook vanished, thus also when
+ the hook is not in call.
+
2001-03-08 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* configure.in (FLAG_DOES_NOT_WORK): Fix typo and thus bug #51862.
diff --git a/docs/reference/glib/tmpl/glib-unused.sgml b/docs/reference/glib/tmpl/glib-unused.sgml
index 63b8f6d70..ac05685f3 100644
--- a/docs/reference/glib/tmpl/glib-unused.sgml
+++ b/docs/reference/glib/tmpl/glib-unused.sgml
@@ -17,6 +17,20 @@
@s2:
@Returns:
+<!-- ##### USER_FUNCTION GHookFreeFunc ##### -->
+<para>
+
+</para>
+
+@hook_list:
+@hook:
+
+<!-- ##### MACRO G_HOOK_DEFERRED_DESTROY ##### -->
+<para>
+
+</para>
+
+
<!-- ##### MACRO access ##### -->
<para>
diff --git a/docs/reference/glib/tmpl/hooks.sgml b/docs/reference/glib/tmpl/hooks.sgml
index 47cf06e1f..4ebf12d0b 100644
--- a/docs/reference/glib/tmpl/hooks.sgml
+++ b/docs/reference/glib/tmpl/hooks.sgml
@@ -68,8 +68,7 @@ and the list of hook functions can be invoked.
@is_setup:
@hooks:
@hook_memchunk:
-@hook_free:
-@hook_destroy:
+@finalize_hook:
<!-- ##### STRUCT GHook ##### -->
<para>
@@ -153,6 +152,8 @@ and the list of hook functions can be invoked.
</para>
@hook:
+@marshal_data:
+<!-- # Unused Parameters # -->
@data:
@@ -162,24 +163,10 @@ and the list of hook functions can be invoked.
</para>
@hook:
-@data:
+@marshal_data:
@Returns:
-
-
-<!-- ##### USER_FUNCTION GHookFreeFunc ##### -->
-<para>
-
-</para>
-
-@hook_list:
-@hook:
-
-
-<!-- ##### MACRO G_HOOK_DEFERRED_DESTROY ##### -->
-<para>
-
-</para>
-
+<!-- # Unused Parameters # -->
+@data:
<!-- ##### FUNCTION g_hook_list_init ##### -->
@@ -222,6 +209,8 @@ thread) can be called. If set to FALSE, these are skipped.
@hook_list: a #GHookList.
@may_recurse:
@marshaller:
+@marshal_data:
+<!-- # Unused Parameters # -->
@data:
@@ -233,6 +222,8 @@ thread) can be called. If set to FALSE, these are skipped.
@hook_list: a #GHookList.
@may_recurse:
@marshaller:
+@marshal_data:
+<!-- # Unused Parameters # -->
@data:
diff --git a/docs/reference/glib/tmpl/macros_misc.sgml b/docs/reference/glib/tmpl/macros_misc.sgml
index a7768c733..994ffb730 100644
--- a/docs/reference/glib/tmpl/macros_misc.sgml
+++ b/docs/reference/glib/tmpl/macros_misc.sgml
@@ -66,6 +66,7 @@ only one statement is expected by the compiler.
Portable way to copy <type>va_list</type> variables.
</para>
+<!-- # Unused Parameters # -->
@ap1: the <type>va_list</type> variable to place a copy of @ap2 in.
@ap2: a <type>va_list</type>.
diff --git a/docs/reference/gobject/tmpl/gobject-unused.sgml b/docs/reference/gobject/tmpl/gobject-unused.sgml
index aee4d7ab6..fff0ee7ee 100644
--- a/docs/reference/gobject/tmpl/gobject-unused.sgml
+++ b/docs/reference/gobject/tmpl/gobject-unused.sgml
@@ -1,3 +1,24 @@
+<!-- ##### FUNCTION g_param_spec_string_c ##### -->
+<para>
+
+</para>
+
+@name:
+@nick:
+@blurb:
+@default_value:
+@flags:
+@Returns:
+
+<!-- ##### FUNCTION g_signal_add_emission_hook_full ##### -->
+<para>
+
+</para>
+
+@signal_id:
+@closure:
+@Returns:
+
<!-- ##### FUNCTION g_type_value_is_a ##### -->
<para>
Determines if @value is a #GValue whose type conforms to @type.
diff --git a/docs/reference/gobject/tmpl/signals.sgml b/docs/reference/gobject/tmpl/signals.sgml
index 4445fa03d..6d3f02f44 100644
--- a/docs/reference/gobject/tmpl/signals.sgml
+++ b/docs/reference/gobject/tmpl/signals.sgml
@@ -96,10 +96,13 @@ value returned by the last callback.
@ihint: Signal invokation hint, see #GSignalInvocationHint.
@return_accu: Accumulator to collect callback return values in, this
is the return value of the current signal emission.
-@return_value: The return value of the most recent callback function.
+@handler_return:
+@data:
@Returns: The accumulator function returns whether the signal emission
should be aborted. Returning %FALSE means to abort the
current emission and %TRUE is returned for continuation.
+<!-- # Unused Parameters # -->
+@return_value: The return value of the most recent callback function.
<!-- ##### TYPEDEF GSignalCMarshaller ##### -->
@@ -120,6 +123,7 @@ signal system.
@ihint:
@n_param_values:
@param_values:
+@data:
@Returns:
<!-- # Unused Parameters # -->
@signal_id:
@@ -213,6 +217,7 @@ filled in by the g_signal_query() function.
@signal_flags:
@class_offset:
@accumulator:
+@accu_data:
@c_marshaller:
@return_type:
@n_params:
@@ -230,6 +235,7 @@ filled in by the g_signal_query() function.
@signal_flags:
@class_closure:
@accumulator:
+@accu_data:
@c_marshaller:
@return_type:
@n_params:
@@ -247,6 +253,7 @@ filled in by the g_signal_query() function.
@signal_flags:
@class_closure:
@accumulator:
+@accu_data:
@c_marshaller:
@return_type:
@n_params:
@@ -563,16 +570,6 @@ otherwise.
@detail:
-<!-- ##### FUNCTION g_signal_add_emission_hook_full ##### -->
-<para>
-
-</para>
-
-@signal_id:
-@closure:
-@Returns:
-
-
<!-- ##### FUNCTION g_signal_remove_emission_hook ##### -->
<para>
diff --git a/docs/reference/gobject/tmpl/standard_params.sgml b/docs/reference/gobject/tmpl/standard_params.sgml
index 08b218caf..3019ea8eb 100644
--- a/docs/reference/gobject/tmpl/standard_params.sgml
+++ b/docs/reference/gobject/tmpl/standard_params.sgml
@@ -593,19 +593,6 @@ Standard Parameter Types
@Returns:
-<!-- ##### FUNCTION g_param_spec_string_c ##### -->
-<para>
-
-</para>
-
-@name:
-@nick:
-@blurb:
-@default_value:
-@flags:
-@Returns:
-
-
<!-- ##### FUNCTION g_param_spec_boxed ##### -->
<para>
diff --git a/docs/reference/gobject/tmpl/types.sgml b/docs/reference/gobject/tmpl/types.sgml
index 87f848d1f..4aa4b014e 100644
--- a/docs/reference/gobject/tmpl/types.sgml
+++ b/docs/reference/gobject/tmpl/types.sgml
@@ -201,6 +201,7 @@ The predefined identifiers of the reserved fundamental types.
@G_TYPE_RESERVED_BSE_LAST: Last fundamental type ID reserved for BSE.
@G_TYPE_RESERVED_LAST_FUNDAMENTAL: Last reserved fundamental type ID.
@G_TYPE_CLOSURE:
+@G_TYPE_VALUE:
@G_TYPE_VALUE_ARRAY:
@G_TYPE_PARAM_CHAR: Identifier for the "#GParamSpecChar" type.
@G_TYPE_PARAM_UCHAR: Identifier for the "#GParamSpecUChar" type.
diff --git a/ghook.c b/ghook.c
index ddc6eb73e..53963a135 100644
--- a/ghook.c
+++ b/ghook.c
@@ -39,12 +39,26 @@
/* --- functions --- */
+static void
+default_finalize_hook (GHookList *hook_list,
+ GHook *hook)
+{
+ GDestroyNotify destroy = hook->destroy;
+
+ if (destroy)
+ {
+ hook->destroy = NULL;
+ destroy (hook->data);
+ }
+}
+
void
g_hook_list_init (GHookList *hook_list,
guint hook_size)
{
g_return_if_fail (hook_list != NULL);
g_return_if_fail (hook_size >= sizeof (GHook));
+ g_return_if_fail (hook_size < 65536);
hook_list->seq_id = 1;
hook_list->hook_size = hook_size;
@@ -54,8 +68,7 @@ g_hook_list_init (GHookList *hook_list,
hook_size,
hook_size * G_HOOKS_PREALLOC,
G_ALLOC_AND_FREE);
- hook_list->hook_free = NULL;
- hook_list->hook_destroy = NULL;
+ hook_list->finalize_hook = default_finalize_hook;
}
void
@@ -87,6 +100,8 @@ g_hook_list_clear (GHookList *hook_list)
hook = tmp;
}
while (hook);
+ if (hook_list->hook_memchunk)
+ g_warning (G_STRLOC ": failed to clear hooklist, unconsolidated references on hooks left");
}
}
@@ -119,10 +134,9 @@ g_hook_free (GHookList *hook_list,
g_return_if_fail (hook_list->is_setup);
g_return_if_fail (hook != NULL);
g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
+ g_return_if_fail (!G_HOOK_IN_CALL (hook));
- if (hook_list->hook_free)
- hook_list->hook_free (hook_list, hook);
-
+ hook_list->finalize_hook (hook_list, hook);
g_chunk_free (hook, hook_list->hook_memchunk);
}
@@ -132,23 +146,11 @@ g_hook_destroy_link (GHookList *hook_list,
{
g_return_if_fail (hook_list != NULL);
g_return_if_fail (hook != NULL);
-
+
+ hook->flags &= ~G_HOOK_FLAG_ACTIVE;
if (hook->hook_id)
{
hook->hook_id = 0;
- hook->flags &= ~G_HOOK_FLAG_ACTIVE;
- if (hook_list->hook_destroy)
- {
- if (hook_list->hook_destroy != G_HOOK_DEFERRED_DESTROY)
- hook_list->hook_destroy (hook_list, hook);
- }
- else if (hook->destroy)
- {
- hook->destroy (hook->data);
- hook->data = NULL;
- hook->func = NULL;
- hook->destroy = NULL;
- }
g_hook_unref (hook_list, hook); /* counterpart to g_hook_insert_before */
}
}
@@ -186,7 +188,7 @@ g_hook_unref (GHookList *hook_list,
{
g_return_if_fail (hook->hook_id == 0);
g_return_if_fail (!G_HOOK_IN_CALL (hook));
-
+
if (hook->prev)
hook->prev->next = hook->next;
else
@@ -244,7 +246,7 @@ g_hook_insert_before (GHookList *hook_list,
g_return_if_fail (hook_list->is_setup);
g_return_if_fail (hook != NULL);
g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
- g_return_if_fail (hook->func != NULL);
+ g_return_if_fail (hook->ref_count == 0);
hook->hook_id = hook_list->seq_id++;
hook->ref_count = 1; /* counterpart to g_hook_destroy_link */
diff --git a/ghook.h b/ghook.h
index fe350e18e..2f96d0d22 100644
--- a/ghook.h
+++ b/ghook.h
@@ -31,6 +31,8 @@
G_BEGIN_DECLS
+
+/* --- typedefs --- */
typedef struct _GHook GHook;
typedef struct _GHookList GHookList;
@@ -39,37 +41,32 @@ typedef gint (*GHookCompareFunc) (GHook *new_hook,
typedef gboolean (*GHookFindFunc) (GHook *hook,
gpointer data);
typedef void (*GHookMarshaller) (GHook *hook,
- gpointer data);
+ gpointer marshal_data);
typedef gboolean (*GHookCheckMarshaller) (GHook *hook,
- gpointer data);
+ gpointer marshal_data);
typedef void (*GHookFunc) (gpointer data);
typedef gboolean (*GHookCheckFunc) (gpointer data);
-typedef void (*GHookFreeFunc) (GHookList *hook_list,
+typedef void (*GHookFinalizeFunc) (GHookList *hook_list,
GHook *hook);
-
-/* Callback maintenance functions
- */
-#define G_HOOK_FLAG_USER_SHIFT (4)
typedef enum
{
- G_HOOK_FLAG_ACTIVE = 1 << 0,
- G_HOOK_FLAG_IN_CALL = 1 << 1,
- G_HOOK_FLAG_MASK = 0x0f
+ G_HOOK_FLAG_ACTIVE = 1 << 0,
+ G_HOOK_FLAG_IN_CALL = 1 << 1,
+ G_HOOK_FLAG_MASK = 0x0f
} GHookFlagMask;
+#define G_HOOK_FLAG_USER_SHIFT (4)
-#define G_HOOK_DEFERRED_DESTROY ((GHookFreeFunc) 0x01)
+/* --- structures --- */
struct _GHookList
{
- guint seq_id;
- guint hook_size;
- guint is_setup : 1;
- GHook *hooks;
- GMemChunk *hook_memchunk;
- GHookFreeFunc hook_free; /* virtual function */
- GHookFreeFunc hook_destroy; /* virtual function */
+ guint seq_id;
+ guint hook_size : 16;
+ guint is_setup : 1;
+ GHook *hooks;
+ GMemChunk *hook_memchunk;
+ GHookFinalizeFunc finalize_hook;
};
-
struct _GHook
{
gpointer data;
@@ -82,17 +79,25 @@ struct _GHook
GDestroyNotify destroy;
};
-#define G_HOOK_ACTIVE(hook) ((((GHook*) hook)->flags & \
+
+/* --- macros --- */
+#define G_HOOK(hook) ((GHook*) (hook))
+#define G_HOOK_FLAGS(hook) (G_HOOK (hook)->flags)
+#define G_HOOK_ACTIVE(hook) ((G_HOOK_FLAGS (hook) & \
G_HOOK_FLAG_ACTIVE) != 0)
-#define G_HOOK_IN_CALL(hook) ((((GHook*) hook)->flags & \
+#define G_HOOK_IN_CALL(hook) ((G_HOOK_FLAGS (hook) & \
G_HOOK_FLAG_IN_CALL) != 0)
-#define G_HOOK_IS_VALID(hook) (((GHook*) hook)->hook_id != 0 && \
- G_HOOK_ACTIVE (hook))
-#define G_HOOK_IS_UNLINKED(hook) (((GHook*) hook)->next == NULL && \
- ((GHook*) hook)->prev == NULL && \
- ((GHook*) hook)->hook_id == 0 && \
- ((GHook*) hook)->ref_count == 0)
+#define G_HOOK_IS_VALID(hook) (G_HOOK (hook)->hook_id != 0 && \
+ (G_HOOK_FLAGS (hook) & \
+ G_HOOK_FLAG_ACTIVE))
+#define G_HOOK_IS_UNLINKED(hook) (G_HOOK (hook)->next == NULL && \
+ G_HOOK (hook)->prev == NULL && \
+ G_HOOK (hook)->hook_id == 0 && \
+ G_HOOK (hook)->ref_count == 0)
+
+/* --- prototypes --- */
+/* callback mainenance functions */
void g_hook_list_init (GHookList *hook_list,
guint hook_size);
void g_hook_list_clear (GHookList *hook_list);
@@ -140,15 +145,12 @@ GHook* g_hook_first_valid (GHookList *hook_list,
GHook* g_hook_next_valid (GHookList *hook_list,
GHook *hook,
gboolean may_be_in_call);
-
/* GHookCompareFunc implementation to insert hooks sorted by their id */
gint g_hook_compare_ids (GHook *new_hook,
GHook *sibling);
-
/* convenience macros */
#define g_hook_append( hook_list, hook ) \
g_hook_insert_before ((hook_list), NULL, (hook))
-
/* invoke all valid hooks with the (*GHookFunc) signature.
*/
void g_hook_list_invoke (GHookList *hook_list,
@@ -163,11 +165,11 @@ void g_hook_list_invoke_check (GHookList *hook_list,
void g_hook_list_marshal (GHookList *hook_list,
gboolean may_recurse,
GHookMarshaller marshaller,
- gpointer data);
+ gpointer marshal_data);
void g_hook_list_marshal_check (GHookList *hook_list,
gboolean may_recurse,
GHookCheckMarshaller marshaller,
- gpointer data);
+ gpointer marshal_data);
G_END_DECLS
diff --git a/glib/ghook.c b/glib/ghook.c
index ddc6eb73e..53963a135 100644
--- a/glib/ghook.c
+++ b/glib/ghook.c
@@ -39,12 +39,26 @@
/* --- functions --- */
+static void
+default_finalize_hook (GHookList *hook_list,
+ GHook *hook)
+{
+ GDestroyNotify destroy = hook->destroy;
+
+ if (destroy)
+ {
+ hook->destroy = NULL;
+ destroy (hook->data);
+ }
+}
+
void
g_hook_list_init (GHookList *hook_list,
guint hook_size)
{
g_return_if_fail (hook_list != NULL);
g_return_if_fail (hook_size >= sizeof (GHook));
+ g_return_if_fail (hook_size < 65536);
hook_list->seq_id = 1;
hook_list->hook_size = hook_size;
@@ -54,8 +68,7 @@ g_hook_list_init (GHookList *hook_list,
hook_size,
hook_size * G_HOOKS_PREALLOC,
G_ALLOC_AND_FREE);
- hook_list->hook_free = NULL;
- hook_list->hook_destroy = NULL;
+ hook_list->finalize_hook = default_finalize_hook;
}
void
@@ -87,6 +100,8 @@ g_hook_list_clear (GHookList *hook_list)
hook = tmp;
}
while (hook);
+ if (hook_list->hook_memchunk)
+ g_warning (G_STRLOC ": failed to clear hooklist, unconsolidated references on hooks left");
}
}
@@ -119,10 +134,9 @@ g_hook_free (GHookList *hook_list,
g_return_if_fail (hook_list->is_setup);
g_return_if_fail (hook != NULL);
g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
+ g_return_if_fail (!G_HOOK_IN_CALL (hook));
- if (hook_list->hook_free)
- hook_list->hook_free (hook_list, hook);
-
+ hook_list->finalize_hook (hook_list, hook);
g_chunk_free (hook, hook_list->hook_memchunk);
}
@@ -132,23 +146,11 @@ g_hook_destroy_link (GHookList *hook_list,
{
g_return_if_fail (hook_list != NULL);
g_return_if_fail (hook != NULL);
-
+
+ hook->flags &= ~G_HOOK_FLAG_ACTIVE;
if (hook->hook_id)
{
hook->hook_id = 0;
- hook->flags &= ~G_HOOK_FLAG_ACTIVE;
- if (hook_list->hook_destroy)
- {
- if (hook_list->hook_destroy != G_HOOK_DEFERRED_DESTROY)
- hook_list->hook_destroy (hook_list, hook);
- }
- else if (hook->destroy)
- {
- hook->destroy (hook->data);
- hook->data = NULL;
- hook->func = NULL;
- hook->destroy = NULL;
- }
g_hook_unref (hook_list, hook); /* counterpart to g_hook_insert_before */
}
}
@@ -186,7 +188,7 @@ g_hook_unref (GHookList *hook_list,
{
g_return_if_fail (hook->hook_id == 0);
g_return_if_fail (!G_HOOK_IN_CALL (hook));
-
+
if (hook->prev)
hook->prev->next = hook->next;
else
@@ -244,7 +246,7 @@ g_hook_insert_before (GHookList *hook_list,
g_return_if_fail (hook_list->is_setup);
g_return_if_fail (hook != NULL);
g_return_if_fail (G_HOOK_IS_UNLINKED (hook));
- g_return_if_fail (hook->func != NULL);
+ g_return_if_fail (hook->ref_count == 0);
hook->hook_id = hook_list->seq_id++;
hook->ref_count = 1; /* counterpart to g_hook_destroy_link */
diff --git a/glib/ghook.h b/glib/ghook.h
index fe350e18e..2f96d0d22 100644
--- a/glib/ghook.h
+++ b/glib/ghook.h
@@ -31,6 +31,8 @@
G_BEGIN_DECLS
+
+/* --- typedefs --- */
typedef struct _GHook GHook;
typedef struct _GHookList GHookList;
@@ -39,37 +41,32 @@ typedef gint (*GHookCompareFunc) (GHook *new_hook,
typedef gboolean (*GHookFindFunc) (GHook *hook,
gpointer data);
typedef void (*GHookMarshaller) (GHook *hook,
- gpointer data);
+ gpointer marshal_data);
typedef gboolean (*GHookCheckMarshaller) (GHook *hook,
- gpointer data);
+ gpointer marshal_data);
typedef void (*GHookFunc) (gpointer data);
typedef gboolean (*GHookCheckFunc) (gpointer data);
-typedef void (*GHookFreeFunc) (GHookList *hook_list,
+typedef void (*GHookFinalizeFunc) (GHookList *hook_list,
GHook *hook);
-
-/* Callback maintenance functions
- */
-#define G_HOOK_FLAG_USER_SHIFT (4)
typedef enum
{
- G_HOOK_FLAG_ACTIVE = 1 << 0,
- G_HOOK_FLAG_IN_CALL = 1 << 1,
- G_HOOK_FLAG_MASK = 0x0f
+ G_HOOK_FLAG_ACTIVE = 1 << 0,
+ G_HOOK_FLAG_IN_CALL = 1 << 1,
+ G_HOOK_FLAG_MASK = 0x0f
} GHookFlagMask;
+#define G_HOOK_FLAG_USER_SHIFT (4)
-#define G_HOOK_DEFERRED_DESTROY ((GHookFreeFunc) 0x01)
+/* --- structures --- */
struct _GHookList
{
- guint seq_id;
- guint hook_size;
- guint is_setup : 1;
- GHook *hooks;
- GMemChunk *hook_memchunk;
- GHookFreeFunc hook_free; /* virtual function */
- GHookFreeFunc hook_destroy; /* virtual function */
+ guint seq_id;
+ guint hook_size : 16;
+ guint is_setup : 1;
+ GHook *hooks;
+ GMemChunk *hook_memchunk;
+ GHookFinalizeFunc finalize_hook;
};
-
struct _GHook
{
gpointer data;
@@ -82,17 +79,25 @@ struct _GHook
GDestroyNotify destroy;
};
-#define G_HOOK_ACTIVE(hook) ((((GHook*) hook)->flags & \
+
+/* --- macros --- */
+#define G_HOOK(hook) ((GHook*) (hook))
+#define G_HOOK_FLAGS(hook) (G_HOOK (hook)->flags)
+#define G_HOOK_ACTIVE(hook) ((G_HOOK_FLAGS (hook) & \
G_HOOK_FLAG_ACTIVE) != 0)
-#define G_HOOK_IN_CALL(hook) ((((GHook*) hook)->flags & \
+#define G_HOOK_IN_CALL(hook) ((G_HOOK_FLAGS (hook) & \
G_HOOK_FLAG_IN_CALL) != 0)
-#define G_HOOK_IS_VALID(hook) (((GHook*) hook)->hook_id != 0 && \
- G_HOOK_ACTIVE (hook))
-#define G_HOOK_IS_UNLINKED(hook) (((GHook*) hook)->next == NULL && \
- ((GHook*) hook)->prev == NULL && \
- ((GHook*) hook)->hook_id == 0 && \
- ((GHook*) hook)->ref_count == 0)
+#define G_HOOK_IS_VALID(hook) (G_HOOK (hook)->hook_id != 0 && \
+ (G_HOOK_FLAGS (hook) & \
+ G_HOOK_FLAG_ACTIVE))
+#define G_HOOK_IS_UNLINKED(hook) (G_HOOK (hook)->next == NULL && \
+ G_HOOK (hook)->prev == NULL && \
+ G_HOOK (hook)->hook_id == 0 && \
+ G_HOOK (hook)->ref_count == 0)
+
+/* --- prototypes --- */
+/* callback mainenance functions */
void g_hook_list_init (GHookList *hook_list,
guint hook_size);
void g_hook_list_clear (GHookList *hook_list);
@@ -140,15 +145,12 @@ GHook* g_hook_first_valid (GHookList *hook_list,
GHook* g_hook_next_valid (GHookList *hook_list,
GHook *hook,
gboolean may_be_in_call);
-
/* GHookCompareFunc implementation to insert hooks sorted by their id */
gint g_hook_compare_ids (GHook *new_hook,
GHook *sibling);
-
/* convenience macros */
#define g_hook_append( hook_list, hook ) \
g_hook_insert_before ((hook_list), NULL, (hook))
-
/* invoke all valid hooks with the (*GHookFunc) signature.
*/
void g_hook_list_invoke (GHookList *hook_list,
@@ -163,11 +165,11 @@ void g_hook_list_invoke_check (GHookList *hook_list,
void g_hook_list_marshal (GHookList *hook_list,
gboolean may_recurse,
GHookMarshaller marshaller,
- gpointer data);
+ gpointer marshal_data);
void g_hook_list_marshal_check (GHookList *hook_list,
gboolean may_recurse,
GHookCheckMarshaller marshaller,
- gpointer data);
+ gpointer marshal_data);
G_END_DECLS
diff --git a/gobject/ChangeLog b/gobject/ChangeLog
index 7a9dcd29b..ffe8c7605 100644
--- a/gobject/ChangeLog
+++ b/gobject/ChangeLog
@@ -1,3 +1,22 @@
+Thu Mar 8 16:35:48 2001 Tim Janik <timj@gtk.org>
+
+ * gparamspecs.[hc]: s/g_param_spec_string_c/g_param_spec_stringc/.
+
+ * gsignal.[hc]: fixed accumulator invocation, implemented emission
+ hooks. and no, neither of these callbacks are called via a closure,
+ language bindings can wrap the accumulator and emission hook
+ interface, they already get parameters marshalled into a GValue array.
+ (g_signal_connect): removed this function as its C specific, doesn't
+ cover the swapped argument, is too close to its broken original
+ gtk_signal_connect() and creates demand for _swapped, _after and
+ _swapped_after variants <brrr>.
+ (g_signal_connectc): convenience macro to connect a C handler
+ func with data, like the old g_signal_connect() plus swapped
+ argument.
+
+ * gtype.h:
+ * gboxed.c: added G_TYPE_VALUE boxed type.
+
Wed Mar 7 19:02:51 2001 Tim Janik <timj@gtk.org>
* gtype.c (type_node_add_iface_entry_W): catch when adding an interface
diff --git a/gobject/gboxed.c b/gobject/gboxed.c
index 5356513e9..7dd240b7d 100644
--- a/gobject/gboxed.c
+++ b/gobject/gboxed.c
@@ -65,6 +65,30 @@ value_meminit (GValue *value,
}
static gpointer
+value_copy (gpointer boxed)
+{
+ const GValue *src_value = boxed;
+ GValue *dest_value = g_new0 (GValue, 1);
+
+ if (G_VALUE_TYPE (src_value))
+ {
+ g_value_init (dest_value, G_VALUE_TYPE (src_value));
+ g_value_copy (src_value, dest_value);
+ }
+ return dest_value;
+}
+
+static void
+value_free (gpointer boxed)
+{
+ GValue *value = boxed;
+
+ if (G_VALUE_TYPE (value))
+ g_value_unset (value);
+ g_free (value);
+}
+
+static gpointer
value_array_init (void)
{
return g_value_array_new (0);
@@ -103,6 +127,15 @@ g_boxed_type_init (void) /* sync with gtype.c */
TRUE);
g_assert (type == G_TYPE_CLOSURE);
+ /* boxed: G_TYPE_VALUE
+ */
+ type = g_boxed_type_register_static ("GValue",
+ (GBoxedInitFunc) NULL,
+ value_copy,
+ value_free,
+ FALSE);
+ g_assert (type == G_TYPE_VALUE);
+
/* boxed: G_TYPE_VALUE_ARRAY
*/
type = g_boxed_type_register_static ("GValueArray",
diff --git a/gobject/gobject.c b/gobject/gobject.c
index 690fe6b7c..f9ade44c5 100644
--- a/gobject/gobject.c
+++ b/gobject/gobject.c
@@ -271,8 +271,8 @@ g_object_do_class_init (GObjectClass *class)
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
G_STRUCT_OFFSET (GObjectClass, properties_changed),
- NULL, /* accumulator */
- g_cclosure_marshal_VOID__UINT_POINTER,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__UINT_POINTER,
G_TYPE_NONE,
2, G_TYPE_UINT, G_TYPE_POINTER);
gobject_signals[NOTIFY] =
@@ -280,7 +280,7 @@ g_object_do_class_init (GObjectClass *class)
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED | G_SIGNAL_NO_HOOKS,
G_STRUCT_OFFSET (GObjectClass, notify),
- NULL, /* accumulator */
+ NULL, NULL,
g_cclosure_marshal_VOID__PARAM,
G_TYPE_NONE,
1, G_TYPE_PARAM);
diff --git a/gobject/gparamspecs.c b/gobject/gparamspecs.c
index 44dca645d..35f60e015 100644
--- a/gobject/gparamspecs.c
+++ b/gobject/gparamspecs.c
@@ -1453,11 +1453,11 @@ g_param_spec_string (const gchar *name,
}
GParamSpec*
-g_param_spec_string_c (const gchar *name,
- const gchar *nick,
- const gchar *blurb,
- const gchar *default_value,
- GParamFlags flags)
+g_param_spec_stringc (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ const gchar *default_value,
+ GParamFlags flags)
{
GParamSpecString *sspec = g_param_spec_internal (G_TYPE_PARAM_STRING,
name,
diff --git a/gobject/gparamspecs.h b/gobject/gparamspecs.h
index 1072a4b95..ecfbf27c5 100644
--- a/gobject/gparamspecs.h
+++ b/gobject/gparamspecs.h
@@ -295,7 +295,7 @@ GParamSpec* g_param_spec_string (const gchar *name,
const gchar *blurb,
const gchar *default_value,
GParamFlags flags);
-GParamSpec* g_param_spec_string_c (const gchar *name,
+GParamSpec* g_param_spec_stringc (const gchar *name,
const gchar *nick,
const gchar *blurb,
const gchar *default_value,
diff --git a/gobject/gsignal.c b/gobject/gsignal.c
index 5cad4bb7a..aaeedb797 100644
--- a/gobject/gsignal.c
+++ b/gobject/gsignal.c
@@ -27,6 +27,8 @@
#include "gsignal.h"
#include "gbsearcharray.h"
#include "gvaluecollector.h"
+#include "gvaluetypes.h"
+#include "gboxed.h"
#include <string.h>
@@ -147,6 +149,11 @@ static gboolean signal_emit_R (SignalNode *node,
/* --- structures --- */
+typedef struct
+{
+ GSignalAccumulator func;
+ gpointer data;
+} SignalAccumulator;
struct _SignalNode
{
/* permanent portion */
@@ -161,7 +168,7 @@ struct _SignalNode
GType *param_types; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */
GType return_type; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */
GClosure *class_closure;
- GSignalAccumulator accumulator;
+ SignalAccumulator *accumulator;
GSignalCMarshaller c_marshaller;
GHookList *emission_hooks;
};
@@ -723,6 +730,85 @@ g_signal_stop_emission (gpointer instance,
G_UNLOCK (g_signal_mutex);
}
+static void
+signal_finalize_hook (GHookList *hook_list,
+ GHook *hook)
+{
+ GDestroyNotify destroy = hook->destroy;
+
+ if (destroy)
+ {
+ hook->destroy = NULL;
+ G_UNLOCK (g_signal_mutex);
+ destroy (hook->data);
+ G_LOCK (g_signal_mutex);
+ }
+}
+
+guint
+g_signal_add_emission_hook (guint signal_id,
+ GQuark detail,
+ GSignalEmissionHook hook_func,
+ gpointer hook_data,
+ GDestroyNotify data_destroy)
+{
+ static guint seq_hook_id = 1;
+ SignalNode *node;
+ GHook *hook;
+
+ g_return_val_if_fail (signal_id > 0, 0);
+ g_return_val_if_fail (hook_func != NULL, 0);
+
+ G_LOCK (g_signal_mutex);
+ node = LOOKUP_SIGNAL_NODE (signal_id);
+ if (!node || node->destroyed || (node->flags & G_SIGNAL_NO_HOOKS))
+ {
+ g_warning ("%s: invalid signal id `%u'", G_STRLOC, signal_id);
+ G_UNLOCK (g_signal_mutex);
+ 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_UNLOCK (g_signal_mutex);
+ return 0;
+ }
+ if (!node->emission_hooks)
+ {
+ node->emission_hooks = g_new (GHookList, 1);
+ g_hook_list_init (node->emission_hooks, sizeof (GHook));
+ node->emission_hooks->finalize_hook = signal_finalize_hook;
+ }
+ hook = g_hook_alloc (node->emission_hooks);
+ hook->data = hook_data;
+ hook->func = hook_func;
+ hook->destroy = data_destroy;
+ node->emission_hooks->seq_id = seq_hook_id;
+ g_hook_append (node->emission_hooks, hook);
+ seq_hook_id = node->emission_hooks->seq_id;
+ G_UNLOCK (g_signal_mutex);
+
+ return hook->hook_id;
+}
+
+void
+g_signal_remove_emission_hook (guint signal_id,
+ guint hook_id)
+{
+ SignalNode *node;
+
+ g_return_if_fail (signal_id > 0);
+ g_return_if_fail (hook_id > 0);
+
+ G_LOCK (g_signal_mutex);
+ node = LOOKUP_SIGNAL_NODE (signal_id);
+ if (!node || node->destroyed)
+ g_warning ("%s: invalid signal id `%u'", G_STRLOC, signal_id);
+ else if (!node->emission_hooks || !g_hook_destroy (node->emission_hooks, hook_id))
+ g_warning ("%s: signal \"%s\" had no hook (%u) to remove", G_STRLOC, node->name, hook_id);
+ G_UNLOCK (g_signal_mutex);
+}
+
static inline guint
signal_parse_name (const gchar *name,
GType itype,
@@ -896,6 +982,7 @@ g_signal_new_valist (const gchar *signal_name,
GSignalFlags signal_flags,
GClosure *class_closure,
GSignalAccumulator accumulator,
+ gpointer accu_data,
GSignalCMarshaller c_marshaller,
GType return_type,
guint n_params,
@@ -916,7 +1003,7 @@ g_signal_new_valist (const gchar *signal_name,
param_types = NULL;
signal_id = g_signal_newv (signal_name, itype, signal_flags,
- class_closure, accumulator, c_marshaller,
+ class_closure, accumulator, accu_data, c_marshaller,
return_type, n_params, param_types);
g_free (param_types);
@@ -928,7 +1015,8 @@ g_signal_newc (const gchar *signal_name,
GType itype,
GSignalFlags signal_flags,
guint class_offset,
- GSignalAccumulator accumulator,
+ GSignalAccumulator accumulator,
+ gpointer accu_data,
GSignalCMarshaller c_marshaller,
GType return_type,
guint n_params,
@@ -943,7 +1031,7 @@ g_signal_newc (const gchar *signal_name,
signal_id = g_signal_new_valist (signal_name, itype, signal_flags,
g_signal_type_cclosure_new (itype, class_offset),
- accumulator, c_marshaller,
+ accumulator, accu_data, c_marshaller,
return_type, n_params, args);
va_end (args);
@@ -957,6 +1045,7 @@ g_signal_newv (const gchar *signal_name,
GSignalFlags signal_flags,
GClosure *class_closure,
GSignalAccumulator accumulator,
+ gpointer accu_data,
GSignalCMarshaller c_marshaller,
GType return_type,
guint n_params,
@@ -970,9 +1059,11 @@ g_signal_newv (const gchar *signal_name,
g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
if (n_params)
g_return_val_if_fail (param_types != NULL, 0);
- if (return_type != G_TYPE_NONE)
+ if (return_type == (G_TYPE_NONE & ~G_SIGNAL_TYPE_STATIC_SCOPE))
g_return_val_if_fail (accumulator == NULL, 0);
-
+ if (!accumulator)
+ g_return_val_if_fail (accu_data == NULL, 0);
+
name = g_strdup (signal_name);
g_strdelimit (name, G_STR_DELIMITERS ":^", '_'); // FIXME do character checks like for types
@@ -1048,12 +1139,18 @@ g_signal_newv (const gchar *signal_name,
node->class_closure = class_closure ? g_closure_ref (class_closure) : NULL;
if (class_closure)
g_closure_sink (class_closure);
- node->accumulator = accumulator;
+ if (accumulator)
+ {
+ node->accumulator = g_new (SignalAccumulator, 1);
+ node->accumulator->func = accumulator;
+ node->accumulator->data = accu_data;
+ }
+ else
+ node->accumulator = NULL;
node->c_marshaller = c_marshaller;
node->emission_hooks = NULL;
if (node->c_marshaller && class_closure && G_CLOSURE_NEEDS_MARSHAL (class_closure))
g_closure_set_marshal (class_closure, node->c_marshaller);
-
G_UNLOCK (g_signal_mutex);
return signal_id;
}
@@ -1092,6 +1189,7 @@ signal_destroy_R (SignalNode *signal_node)
G_UNLOCK (g_signal_mutex);
g_free (node.param_types);
g_closure_unref (node.class_closure);
+ g_free (node.accumulator);
if (node.emission_hooks)
{
g_hook_list_clear (node.emission_hooks);
@@ -1740,21 +1838,37 @@ g_signal_emit_by_name (gpointer instance,
g_warning ("%s: signal name `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
}
+static inline gboolean
+accumulate (GSignalInvocationHint *ihint,
+ GValue *return_accu,
+ GValue *handler_return,
+ SignalAccumulator *accumulator)
+{
+ gboolean continue_emission;
+
+ if (!accumulator)
+ return TRUE;
+
+ continue_emission = accumulator->func (ihint, return_accu, handler_return, accumulator->data);
+ g_value_reset (handler_return);
+
+ return continue_emission;
+}
+
static gboolean
signal_emit_R (SignalNode *node,
GQuark detail,
gpointer instance,
- GValue *return_value,
+ GValue *emission_return,
const GValue *instance_and_params)
{
EmissionState emission_state = 0;
- GSignalAccumulator accumulator;
+ SignalAccumulator *accumulator;
GSignalInvocationHint ihint;
GClosure *class_closure;
HandlerList *hlist;
Handler *handler_list = NULL;
- GValue accu = { 0, };
- gboolean accu_used = FALSE;
+ GValue *return_accu, accu = { 0, };
guint signal_id = node->signal_id;
gboolean return_value_altered = FALSE;
@@ -1784,7 +1898,12 @@ signal_emit_R (SignalNode *node,
ihint.detail = detail;
accumulator = node->accumulator;
if (accumulator)
- g_value_init (&accu, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
+ {
+ g_value_init (&accu, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
+ return_accu = &accu;
+ }
+ else
+ return_accu = emission_return;
emission_push ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions,
signal_id, detail, instance, &emission_state);
class_closure = node->class_closure;
@@ -1805,26 +1924,14 @@ signal_emit_R (SignalNode *node,
emission_state = EMISSION_RUN;
G_UNLOCK (g_signal_mutex);
- if (accumulator)
- {
- if (accu_used)
- g_value_reset (&accu);
- g_closure_invoke (class_closure,
- &accu,
- node->n_params + 1,
- instance_and_params,
- &ihint);
- if (!accumulator (&ihint, return_value, &accu) &&
- emission_state == EMISSION_RUN)
- emission_state = EMISSION_STOP;
- accu_used = TRUE;
- }
- else
- g_closure_invoke (class_closure,
- return_value,
- node->n_params + 1,
- instance_and_params,
- &ihint);
+ g_closure_invoke (class_closure,
+ return_accu,
+ node->n_params + 1,
+ instance_and_params,
+ &ihint);
+ if (!accumulate (&ihint, emission_return, &accu, accumulator) &&
+ emission_state == EMISSION_RUN)
+ emission_state = EMISSION_STOP;
G_LOCK (g_signal_mutex);
return_value_altered = TRUE;
@@ -1836,11 +1943,31 @@ signal_emit_R (SignalNode *node,
if (node->emission_hooks)
{
- emission_state = EMISSION_HOOK;
+ gboolean need_destroy, was_in_call, may_recurse = TRUE;
+ GHook *hook;
- G_UNLOCK (g_signal_mutex);
- g_print ("emission_hooks()\n");
- G_LOCK (g_signal_mutex);
+ emission_state = EMISSION_HOOK;
+ hook = g_hook_first_valid (node->emission_hooks, may_recurse);
+ while (hook)
+ {
+ GQuark hook_detail = GPOINTER_TO_UINT (hook->func);
+
+ if (!hook_detail || hook_detail == detail)
+ {
+ GSignalEmissionHook hook_func = hook->func;
+
+ was_in_call = G_HOOK_IN_CALL (hook);
+ hook->flags |= G_HOOK_FLAG_IN_CALL;
+ G_UNLOCK (g_signal_mutex);
+ need_destroy = !hook_func (&ihint, node->n_params + 1, instance_and_params, hook->data);
+ G_LOCK (g_signal_mutex);
+ if (!was_in_call)
+ hook->flags &= ~G_HOOK_FLAG_IN_CALL;
+ if (need_destroy)
+ g_hook_destroy_link (node->emission_hooks, hook);
+ }
+ hook = g_hook_next_valid (node->emission_hooks, hook, may_recurse);
+ }
if (emission_state == EMISSION_RESTART)
goto EMIT_RESTART;
@@ -1865,26 +1992,14 @@ signal_emit_R (SignalNode *node,
else if (!handler->block_count && (!handler->detail || handler->detail == detail))
{
G_UNLOCK (g_signal_mutex);
- if (accumulator)
- {
- if (accu_used)
- g_value_reset (&accu);
- g_closure_invoke (handler->closure,
- &accu,
- node->n_params + 1,
- instance_and_params,
- &ihint);
- if (!accumulator (&ihint, return_value, &accu) &&
- emission_state == EMISSION_RUN)
- emission_state = EMISSION_STOP;
- accu_used = TRUE;
- }
- else
- g_closure_invoke (handler->closure,
- return_value,
- node->n_params + 1,
- instance_and_params,
- &ihint);
+ g_closure_invoke (handler->closure,
+ return_accu,
+ node->n_params + 1,
+ instance_and_params,
+ &ihint);
+ if (!accumulate (&ihint, emission_return, &accu, accumulator) &&
+ emission_state == EMISSION_RUN)
+ emission_state = EMISSION_STOP;
G_LOCK (g_signal_mutex);
return_value_altered = TRUE;
@@ -1914,26 +2029,14 @@ signal_emit_R (SignalNode *node,
emission_state = EMISSION_RUN;
G_UNLOCK (g_signal_mutex);
- if (accumulator)
- {
- if (accu_used)
- g_value_reset (&accu);
- g_closure_invoke (class_closure,
- &accu,
- node->n_params + 1,
- instance_and_params,
- &ihint);
- if (!accumulator (&ihint, return_value, &accu) &&
- emission_state == EMISSION_RUN)
- emission_state = EMISSION_STOP;
- accu_used = TRUE;
- }
- else
- g_closure_invoke (class_closure,
- return_value,
- node->n_params + 1,
- instance_and_params,
- &ihint);
+ g_closure_invoke (class_closure,
+ return_accu,
+ node->n_params + 1,
+ instance_and_params,
+ &ihint);
+ if (!accumulate (&ihint, emission_return, &accu, accumulator) &&
+ emission_state == EMISSION_RUN)
+ emission_state = EMISSION_STOP;
G_LOCK (g_signal_mutex);
return_value_altered = TRUE;
@@ -1956,26 +2059,14 @@ signal_emit_R (SignalNode *node,
if (handler->after && !handler->block_count && (!handler->detail || handler->detail == detail))
{
G_UNLOCK (g_signal_mutex);
- if (accumulator)
- {
- if (accu_used)
- g_value_reset (&accu);
- g_closure_invoke (handler->closure,
- &accu,
- node->n_params + 1,
- instance_and_params,
- &ihint);
- if (!accumulator (&ihint, return_value, &accu) &&
- emission_state == EMISSION_RUN)
- emission_state = EMISSION_STOP;
- accu_used = TRUE;
- }
- else
- g_closure_invoke (handler->closure,
- return_value,
- node->n_params + 1,
- instance_and_params,
- &ihint);
+ g_closure_invoke (handler->closure,
+ return_accu,
+ node->n_params + 1,
+ instance_and_params,
+ &ihint);
+ if (!accumulate (&ihint, emission_return, &accu, accumulator) &&
+ emission_state == EMISSION_RUN)
+ emission_state = EMISSION_STOP;
G_LOCK (g_signal_mutex);
return_value_altered = TRUE;
@@ -2008,15 +2099,10 @@ signal_emit_R (SignalNode *node,
emission_state = EMISSION_STOP;
G_UNLOCK (g_signal_mutex);
- if (node->return_type != G_TYPE_NONE)
+ if (node->return_type != G_TYPE_NONE && !accumulator)
{
- if (!accumulator)
- {
- g_value_init (&accu, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
- need_unset = TRUE;
- }
- else if (accu_used)
- g_value_reset (&accu);
+ g_value_init (&accu, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
+ need_unset = TRUE;
}
g_closure_invoke (class_closure,
node->return_type != G_TYPE_NONE ? &accu : NULL,
@@ -2037,14 +2123,12 @@ signal_emit_R (SignalNode *node,
emission_pop ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, &emission_state);
if (accumulator)
g_value_unset (&accu);
-
+
return return_value_altered;
}
/* --- compile standard marshallers --- */
-#include "gvaluetypes.h"
#include "gobject.h"
#include "genums.h"
-#include "gboxed.h"
#include "gmarshal.c"
diff --git a/gobject/gsignal.h b/gobject/gsignal.h
index a1434da7a..476178e7c 100644
--- a/gobject/gsignal.h
+++ b/gobject/gsignal.h
@@ -37,10 +37,12 @@ typedef struct _GSignalInvocationHint GSignalInvocationHint;
typedef GClosureMarshal GSignalCMarshaller;
typedef gboolean (*GSignalEmissionHook) (GSignalInvocationHint *ihint,
guint n_param_values,
- const GValue *param_values);
+ const GValue *param_values,
+ gpointer data);
typedef gboolean (*GSignalAccumulator) (GSignalInvocationHint *ihint,
GValue *return_accu,
- const GValue *return_value);
+ const GValue *handler_return,
+ gpointer data);
/* --- run & match types --- */
@@ -92,7 +94,8 @@ guint g_signal_newv (const gchar *signal_name,
GType itype,
GSignalFlags signal_flags,
GClosure *class_closure,
- GSignalAccumulator accumulator,
+ GSignalAccumulator accumulator,
+ gpointer accu_data,
GSignalCMarshaller c_marshaller,
GType return_type,
guint n_params,
@@ -101,7 +104,8 @@ guint g_signal_new_valist (const gchar *signal_name,
GType itype,
GSignalFlags signal_flags,
GClosure *class_closure,
- GSignalAccumulator accumulator,
+ GSignalAccumulator accumulator,
+ gpointer accu_data,
GSignalCMarshaller c_marshaller,
GType return_type,
guint n_params,
@@ -110,7 +114,8 @@ guint g_signal_newc (const gchar *signal_name,
GType itype,
GSignalFlags signal_flags,
guint class_offset,
- GSignalAccumulator accumulator,
+ GSignalAccumulator accumulator,
+ gpointer accu_data,
GSignalCMarshaller c_marshaller,
GType return_type,
guint n_params,
@@ -137,16 +142,24 @@ void g_signal_query (guint signal_id,
GSignalQuery *query);
guint* g_signal_list_ids (GType itype,
guint *n_ids);
+gboolean g_signal_parse_name (const gchar *detailed_signal,
+ GType itype,
+ guint *signal_id_p,
+ GQuark *detail_p,
+ gboolean force_detail_quark);
/* --- signal emissions --- */
-void g_signal_stop_emission (gpointer instance,
- guint signal_id,
- GQuark detail);
-guint g_signal_add_emission_hook_full (guint signal_id,
- GClosure *closure);
-void g_signal_remove_emission_hook (guint signal_id,
- guint hook_id);
+void g_signal_stop_emission (gpointer instance,
+ guint signal_id,
+ GQuark detail);
+guint g_signal_add_emission_hook (guint signal_id,
+ GQuark quark,
+ GSignalEmissionHook hook_func,
+ gpointer hook_data,
+ GDestroyNotify data_destroy);
+void g_signal_remove_emission_hook (guint signal_id,
+ guint hook_id);
/* --- signal handlers --- */
@@ -154,8 +167,6 @@ gboolean g_signal_has_handler_pending (gpointer instance,
guint signal_id,
GQuark detail,
gboolean may_be_blocked);
-#define g_signal_connect(instance, detailed_signal, c_handler, data) \
- g_signal_connect_data (instance, detailed_signal, c_handler, data, NULL, FALSE, FALSE)
guint g_signal_connect_closure_by_id (gpointer instance,
guint signal_id,
GQuark detail,
@@ -206,13 +217,12 @@ guint g_signal_handlers_disconnect_matched (gpointer instance,
GClosure *closure,
gpointer func,
gpointer data);
-gboolean g_signal_parse_name (const gchar *detailed_signal,
- GType itype,
- guint *signal_id_p,
- GQuark *detail_p,
- gboolean force_detail_quark);
+/* --- convenience --- */
+#define g_signal_connectc(instance, detailed_signal, c_handler, data, swapped) \
+ g_signal_connect_data ((instance), (detailed_signal), (c_handler), (data), NULL, (swapped), FALSE)
+
/*< private >*/
void g_signal_handlers_destroy (gpointer instance);
void _g_signals_destroy (GType itype);
diff --git a/gobject/gtype.h b/gobject/gtype.h
index 9133b2426..e60f0a339 100644
--- a/gobject/gtype.h
+++ b/gobject/gtype.h
@@ -73,7 +73,8 @@ typedef enum /*< skip >*/
/* derived type ids */
G_TYPE_CLOSURE = G_TYPE_DERIVE_ID (G_TYPE_BOXED, 1),
- G_TYPE_VALUE_ARRAY = G_TYPE_DERIVE_ID (G_TYPE_BOXED, 2),
+ G_TYPE_VALUE = G_TYPE_DERIVE_ID (G_TYPE_BOXED, 2),
+ G_TYPE_VALUE_ARRAY = G_TYPE_DERIVE_ID (G_TYPE_BOXED, 3),
G_TYPE_PARAM_CHAR = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 1),
G_TYPE_PARAM_UCHAR = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 2),
G_TYPE_PARAM_BOOLEAN = G_TYPE_DERIVE_ID (G_TYPE_PARAM, 3),