destruction cleanup. there's one ->finalize_hook member in the hooklist
authorTim Janik <timj@gtk.org>
Thu, 8 Mar 2001 16:34:59 +0000 (16:34 +0000)
committerTim Janik <timj@src.gnome.org>
Thu, 8 Mar 2001 16:34:59 +0000 (16:34 +0000)
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.

27 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-12
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
docs/reference/glib/tmpl/glib-unused.sgml
docs/reference/glib/tmpl/hooks.sgml
docs/reference/glib/tmpl/macros_misc.sgml
docs/reference/gobject/tmpl/gobject-unused.sgml
docs/reference/gobject/tmpl/signals.sgml
docs/reference/gobject/tmpl/standard_params.sgml
docs/reference/gobject/tmpl/types.sgml
ghook.c
ghook.h
glib/ghook.c
glib/ghook.h
gobject/ChangeLog
gobject/gboxed.c
gobject/gobject.c
gobject/gparamspecs.c
gobject/gparamspecs.h
gobject/gsignal.c
gobject/gsignal.h
gobject/gtype.h

index 65bc175..f7367cb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Thu Mar  8 16:23:34 2001  Tim Janik  <timj@gtk.org>
+
+       * ghook.[hc]: destruction cleanup. there's one
+       ->finalize_hook member in the hooklist now that gets
+       called when a hook should be destroyed, that's it.
+       that function is guarranteed to be called only when
+       all ref_counts to the hook vanished, thus also when
+       the hook is not in call.
+
 2001-03-08  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
 
        * configure.in (FLAG_DOES_NOT_WORK): Fix typo and thus bug #51862.
index 65bc175..f7367cb 100644 (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.
index 65bc175..f7367cb 100644 (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.
index 65bc175..f7367cb 100644 (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.
index 65bc175..f7367cb 100644 (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.
index 65bc175..f7367cb 100644 (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.
index 65bc175..f7367cb 100644 (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.
index 65bc175..f7367cb 100644 (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.
index 63b8f6d..ac05685 100644 (file)
 @s2: 
 @Returns: 
 
+<!-- ##### USER_FUNCTION GHookFreeFunc ##### -->
+<para>
+
+</para>
+
+@hook_list: 
+@hook: 
+
+<!-- ##### MACRO G_HOOK_DEFERRED_DESTROY ##### -->
+<para>
+
+</para>
+
+
 <!-- ##### MACRO access ##### -->
 <para>
 
index 47cf06e..4ebf12d 100644 (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: 
 
 
index a7768c7..994ffb7 100644 (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>.
 
index aee4d7a..fff0ee7 100644 (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.
index 4445fa0..6d3f02f 100644 (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>
 
index 08b218c..3019ea8 100644 (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>
 
index 87f848d..4aa4b01 100644 (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.
diff --git a/ghook.c b/ghook.c
index ddc6eb7..53963a1 100644 (file)
--- a/ghook.c
+++ b/ghook.c
 
 
 /* --- 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 fe350e1..2f96d0d 100644 (file)
--- a/ghook.h
+++ b/ghook.h
@@ -31,6 +31,8 @@
 
 G_BEGIN_DECLS
 
+
+/* --- typedefs --- */
 typedef struct _GHook          GHook;
 typedef struct _GHookList      GHookList;
 
@@ -39,37 +41,32 @@ typedef gint                (*GHookCompareFunc)     (GHook          *new_hook,
 typedef gboolean       (*GHookFindFunc)        (GHook          *hook,
                                                 gpointer        data);
 typedef void           (*GHookMarshaller)      (GHook          *hook,
-                                                gpointer        data);
+                                                gpointer        marshal_data);
 typedef gboolean       (*GHookCheckMarshaller) (GHook          *hook,
-                                                gpointer        data);
+                                                gpointer        marshal_data);
 typedef void           (*GHookFunc)            (gpointer        data);
 typedef gboolean       (*GHookCheckFunc)       (gpointer        data);
-typedef void           (*GHookFreeFunc)        (GHookList      *hook_list,
+typedef void           (*GHookFinalizeFunc)    (GHookList      *hook_list,
                                                 GHook          *hook);
-
-/* Callback maintenance functions
- */
-#define G_HOOK_FLAG_USER_SHIFT (4)
 typedef enum
 {
-  G_HOOK_FLAG_ACTIVE   = 1 << 0,
-  G_HOOK_FLAG_IN_CALL  = 1 << 1,
-  G_HOOK_FLAG_MASK     = 0x0f
+  G_HOOK_FLAG_ACTIVE       = 1 << 0,
+  G_HOOK_FLAG_IN_CALL      = 1 << 1,
+  G_HOOK_FLAG_MASK         = 0x0f
 } GHookFlagMask;
+#define G_HOOK_FLAG_USER_SHIFT (4)
 
-#define        G_HOOK_DEFERRED_DESTROY ((GHookFreeFunc) 0x01)
 
+/* --- structures --- */
 struct _GHookList
 {
-  guint                 seq_id;
-  guint                 hook_size;
-  guint                 is_setup : 1;
-  GHook                *hooks;
-  GMemChunk    *hook_memchunk;
-  GHookFreeFunc         hook_free; /* virtual function */
-  GHookFreeFunc         hook_destroy; /* virtual function */
+  guint                    seq_id;
+  guint                    hook_size : 16;
+  guint                    is_setup : 1;
+  GHook                   *hooks;
+  GMemChunk       *hook_memchunk;
+  GHookFinalizeFunc finalize_hook;
 };
-
 struct _GHook
 {
   gpointer      data;
@@ -82,17 +79,25 @@ struct _GHook
   GDestroyNotify destroy;
 };
 
-#define        G_HOOK_ACTIVE(hook)             ((((GHook*) hook)->flags & \
+
+/* --- macros --- */
+#define        G_HOOK(hook)                    ((GHook*) (hook))
+#define        G_HOOK_FLAGS(hook)              (G_HOOK (hook)->flags)
+#define        G_HOOK_ACTIVE(hook)             ((G_HOOK_FLAGS (hook) & \
                                          G_HOOK_FLAG_ACTIVE) != 0)
-#define        G_HOOK_IN_CALL(hook)            ((((GHook*) hook)->flags & \
+#define        G_HOOK_IN_CALL(hook)            ((G_HOOK_FLAGS (hook) & \
                                          G_HOOK_FLAG_IN_CALL) != 0)
-#define G_HOOK_IS_VALID(hook)          (((GHook*) hook)->hook_id != 0 && \
-                                        G_HOOK_ACTIVE (hook))
-#define G_HOOK_IS_UNLINKED(hook)       (((GHook*) hook)->next == NULL && \
-                                        ((GHook*) hook)->prev == NULL && \
-                                        ((GHook*) hook)->hook_id == 0 && \
-                                        ((GHook*) hook)->ref_count == 0)
+#define G_HOOK_IS_VALID(hook)          (G_HOOK (hook)->hook_id != 0 && \
+                                        (G_HOOK_FLAGS (hook) & \
+                                          G_HOOK_FLAG_ACTIVE))
+#define G_HOOK_IS_UNLINKED(hook)       (G_HOOK (hook)->next == NULL && \
+                                        G_HOOK (hook)->prev == NULL && \
+                                        G_HOOK (hook)->hook_id == 0 && \
+                                        G_HOOK (hook)->ref_count == 0)
+
 
+/* --- prototypes --- */
+/* callback mainenance functions */
 void    g_hook_list_init               (GHookList              *hook_list,
                                         guint                   hook_size);
 void    g_hook_list_clear              (GHookList              *hook_list);
@@ -140,15 +145,12 @@ GHook*     g_hook_first_valid             (GHookList              *hook_list,
 GHook*  g_hook_next_valid              (GHookList              *hook_list,
                                         GHook                  *hook,
                                         gboolean                may_be_in_call);
-
 /* GHookCompareFunc implementation to insert hooks sorted by their id */
 gint    g_hook_compare_ids             (GHook                  *new_hook,
                                         GHook                  *sibling);
-
 /* convenience macros */
 #define         g_hook_append( hook_list, hook )  \
      g_hook_insert_before ((hook_list), NULL, (hook))
-
 /* invoke all valid hooks with the (*GHookFunc) signature.
  */
 void    g_hook_list_invoke             (GHookList              *hook_list,
@@ -163,11 +165,11 @@ void       g_hook_list_invoke_check       (GHookList              *hook_list,
 void    g_hook_list_marshal            (GHookList              *hook_list,
                                         gboolean                may_recurse,
                                         GHookMarshaller         marshaller,
-                                        gpointer                data);
+                                        gpointer                marshal_data);
 void    g_hook_list_marshal_check      (GHookList              *hook_list,
                                         gboolean                may_recurse,
                                         GHookCheckMarshaller    marshaller,
-                                        gpointer                data);
+                                        gpointer                marshal_data);
 
 G_END_DECLS
 
index ddc6eb7..53963a1 100644 (file)
 
 
 /* --- 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 */
index fe350e1..2f96d0d 100644 (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 & \
+
+/* --- macros --- */
+#define        G_HOOK(hook)                    ((GHook*) (hook))
+#define        G_HOOK_FLAGS(hook)              (G_HOOK (hook)->flags)
+#define        G_HOOK_ACTIVE(hook)             ((G_HOOK_FLAGS (hook) & \
                                          G_HOOK_FLAG_ACTIVE) != 0)
-#define        G_HOOK_IN_CALL(hook)            ((((GHook*) hook)->flags & \
+#define        G_HOOK_IN_CALL(hook)            ((G_HOOK_FLAGS (hook) & \
                                          G_HOOK_FLAG_IN_CALL) != 0)
-#define G_HOOK_IS_VALID(hook)          (((GHook*) hook)->hook_id != 0 && \
-                                        G_HOOK_ACTIVE (hook))
-#define G_HOOK_IS_UNLINKED(hook)       (((GHook*) hook)->next == NULL && \
-                                        ((GHook*) hook)->prev == NULL && \
-                                        ((GHook*) hook)->hook_id == 0 && \
-                                        ((GHook*) hook)->ref_count == 0)
+#define G_HOOK_IS_VALID(hook)          (G_HOOK (hook)->hook_id != 0 && \
+                                        (G_HOOK_FLAGS (hook) & \
+                                          G_HOOK_FLAG_ACTIVE))
+#define G_HOOK_IS_UNLINKED(hook)       (G_HOOK (hook)->next == NULL && \
+                                        G_HOOK (hook)->prev == NULL && \
+                                        G_HOOK (hook)->hook_id == 0 && \
+                                        G_HOOK (hook)->ref_count == 0)
+
 
+/* --- prototypes --- */
+/* callback mainenance functions */
 void    g_hook_list_init               (GHookList              *hook_list,
                                         guint                   hook_size);
 void    g_hook_list_clear              (GHookList              *hook_list);
@@ -140,15 +145,12 @@ GHook*     g_hook_first_valid             (GHookList              *hook_list,
 GHook*  g_hook_next_valid              (GHookList              *hook_list,
                                         GHook                  *hook,
                                         gboolean                may_be_in_call);
-
 /* GHookCompareFunc implementation to insert hooks sorted by their id */
 gint    g_hook_compare_ids             (GHook                  *new_hook,
                                         GHook                  *sibling);
-
 /* convenience macros */
 #define         g_hook_append( hook_list, hook )  \
      g_hook_insert_before ((hook_list), NULL, (hook))
-
 /* invoke all valid hooks with the (*GHookFunc) signature.
  */
 void    g_hook_list_invoke             (GHookList              *hook_list,
@@ -163,11 +165,11 @@ void       g_hook_list_invoke_check       (GHookList              *hook_list,
 void    g_hook_list_marshal            (GHookList              *hook_list,
                                         gboolean                may_recurse,
                                         GHookMarshaller         marshaller,
-                                        gpointer                data);
+                                        gpointer                marshal_data);
 void    g_hook_list_marshal_check      (GHookList              *hook_list,
                                         gboolean                may_recurse,
                                         GHookCheckMarshaller    marshaller,
-                                        gpointer                data);
+                                        gpointer                marshal_data);
 
 G_END_DECLS
 
index 7a9dcd2..ffe8c76 100644 (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
index 5356513..7dd240b 100644 (file)
@@ -65,6 +65,30 @@ value_meminit (GValue *value,
 }
 
 static gpointer
+value_copy (gpointer boxed)
+{
+  const GValue *src_value = boxed;
+  GValue *dest_value = g_new0 (GValue, 1);
+
+  if (G_VALUE_TYPE (src_value))
+    {
+      g_value_init (dest_value, G_VALUE_TYPE (src_value));
+      g_value_copy (src_value, dest_value);
+    }
+  return dest_value;
+}
+
+static void
+value_free (gpointer boxed)
+{
+  GValue *value = boxed;
+
+  if (G_VALUE_TYPE (value))
+    g_value_unset (value);
+  g_free (value);
+}
+
+static gpointer
 value_array_init (void)
 {
   return g_value_array_new (0);
@@ -103,6 +127,15 @@ g_boxed_type_init (void)  /* sync with gtype.c */
                                       TRUE);
   g_assert (type == G_TYPE_CLOSURE);
 
+  /* boxed: G_TYPE_VALUE
+   */
+  type = g_boxed_type_register_static ("GValue",
+                                      (GBoxedInitFunc) NULL,
+                                      value_copy,
+                                      value_free,
+                                      FALSE);
+  g_assert (type == G_TYPE_VALUE);
+
   /* boxed: G_TYPE_VALUE_ARRAY
    */
   type = g_boxed_type_register_static ("GValueArray",
index 690fe6b..f9ade44 100644 (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);
index 44dca64..35f60e0 100644 (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,
index 1072a4b..ecfbf27 100644 (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_string    (const gchar    *name,
                                          const gchar    *nick,
                                          const gchar    *blurb,
                                          const gchar    *default_value,
index 5cad4bb..aaeedb7 100644 (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"
index a1434da..476178e 100644 (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);
index 9133b24..e60f0a3 100644 (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),