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 + + * 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 * 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 + + * 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 * 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 + + * 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 * 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 + + * 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 * 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 + + * 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 * 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 + + * 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 * 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 + + * 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 * 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 + + * 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 * 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: + + + + + +@hook_list: +@hook: + + + + + + + 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: @@ -153,6 +152,8 @@ and the list of hook functions can be invoked. @hook: +@marshal_data: + @data: @@ -162,24 +163,10 @@ and the list of hook functions can be invoked. @hook: -@data: +@marshal_data: @Returns: - - - - - - - -@hook_list: -@hook: - - - - - - - + +@data: @@ -222,6 +209,8 @@ thread) can be called. If set to FALSE, these are skipped. @hook_list: a #GHookList. @may_recurse: @marshaller: +@marshal_data: + @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: + @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 va_list variables. + @ap1: the va_list variable to place a copy of @ap2 in. @ap2: a va_list. 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 @@ + + + + + +@name: +@nick: +@blurb: +@default_value: +@flags: +@Returns: + + + + + + +@signal_id: +@closure: +@Returns: + 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. + +@return_value: The return value of the most recent callback function. @@ -120,6 +123,7 @@ signal system. @ihint: @n_param_values: @param_values: +@data: @Returns: @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: - - - - - -@signal_id: -@closure: -@Returns: - - 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: - - - - - -@name: -@nick: -@blurb: -@default_value: -@flags: -@Returns: - - 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 & \ - G_HOOK_FLAG_ACTIVE) != 0) -#define G_HOOK_IN_CALL(hook) ((((GHook*) hook)->flags & \ - 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) +/* --- 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) ((G_HOOK_FLAGS (hook) & \ + G_HOOK_FLAG_IN_CALL) != 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 & \ - G_HOOK_FLAG_ACTIVE) != 0) -#define G_HOOK_IN_CALL(hook) ((((GHook*) hook)->flags & \ - 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) +/* --- 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) ((G_HOOK_FLAGS (hook) & \ + G_HOOK_FLAG_IN_CALL) != 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 + + * 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 . + (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 * 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 @@ -64,6 +64,30 @@ value_meminit (GValue *value, memset (value->data, 0, sizeof (value->data)); } +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) { @@ -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 @@ -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),