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.
This commit is contained in:
Tim Janik 2001-03-08 16:34:59 +00:00 committed by Tim Janik
parent c811ed93d3
commit 617332234d
27 changed files with 529 additions and 290 deletions

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -17,6 +17,20 @@
@s2:
@Returns:
<!-- ##### USER_FUNCTION GHookFreeFunc ##### -->
<para>
</para>
@hook_list:
@hook:
<!-- ##### MACRO G_HOOK_DEFERRED_DESTROY ##### -->
<para>
</para>
<!-- ##### MACRO access ##### -->
<para>

View File

@ -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:

View File

@ -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>.

View File

@ -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.

View File

@ -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>

View File

@ -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>

View File

@ -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.

44
ghook.c
View File

@ -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 */

70
ghook.h
View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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",

View File

@ -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);

View File

@ -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,

View File

@ -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,

View File

@ -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"

View File

@ -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);

View File

@ -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),