mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-13 22:07:15 +01:00
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:
parent
c811ed93d3
commit
617332234d
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -17,6 +17,20 @@
|
||||
@s2:
|
||||
@Returns:
|
||||
|
||||
<!-- ##### USER_FUNCTION GHookFreeFunc ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@hook_list:
|
||||
@hook:
|
||||
|
||||
<!-- ##### MACRO G_HOOK_DEFERRED_DESTROY ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ##### MACRO access ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -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:
|
||||
|
||||
|
||||
|
@ -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>.
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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
44
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 */
|
||||
|
70
ghook.h
70
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
|
||||
|
||||
|
44
glib/ghook.c
44
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 */
|
||||
|
70
glib/ghook.h
70
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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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",
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
|
@ -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),
|
||||
|
Loading…
x
Reference in New Issue
Block a user