fixed a bag full of subtle bugs of immensive screw-up potential in
authorTim Janik <timj@gtk.org>
Sun, 5 Nov 2000 05:07:26 +0000 (05:07 +0000)
committerTim Janik <timj@src.gnome.org>
Sun, 5 Nov 2000 05:07:26 +0000 (05:07 +0000)
Sun Nov  5 05:22:55 2000  Tim Janik  <timj@gtk.org>

        * gsignal.c:
        fixed a bag full of subtle bugs of immensive screw-up potential in
        handlers_find(), luckily no one found out about them yet ;)
        fixed signal_handlers_foreach_matched_R() so it operates on an
        initial handler list snapshot provided by handlers_find() to work
        around general reentrancy problems and to avoid multiple callback()
        invocations on the same handlers.
        this code is now officially 80% bug free (10% remaining for interface
        types, and 10% remaining for destroyed signals ;)

Sat Nov  4 02:01:33 2000  Tim Janik  <timj@gtk.org>

        * gsignal.c (_g_signals_destroy): valid signal nodes start out at 1.

        * gtypeplugin.[hc]: new files holding a GTypePlugin interface
        implementation that provides the API required by GType to deal with
        dynamically loadable types.

        * gtype.[hc]: displace any GTypePlugin business to gtypeplugin.h.

glib-object.h
glib/glib-object.h
gobject/ChangeLog
gobject/Makefile.am
gobject/gobject.c
gobject/gsignal.c
gobject/gsignal.h
gobject/gtype.c
gobject/gtype.h
gobject/gtypeplugin.c [new file with mode: 0644]
gobject/gtypeplugin.h [new file with mode: 0644]

index 92d9bf9..87ec206 100644 (file)
@@ -28,6 +28,7 @@
 #include       <gobject/gparamspecs.h>
 #include       <gobject/gsignal.h>
 #include       <gobject/gtype.h>
+#include       <gobject/gtypeplugin.h>
 #include       <gobject/gvalue.h>
 #include       <gobject/gvaluetypes.h>
 
index 92d9bf9..87ec206 100644 (file)
@@ -28,6 +28,7 @@
 #include       <gobject/gparamspecs.h>
 #include       <gobject/gsignal.h>
 #include       <gobject/gtype.h>
+#include       <gobject/gtypeplugin.h>
 #include       <gobject/gvalue.h>
 #include       <gobject/gvaluetypes.h>
 
index 3ad2312..5e77f11 100644 (file)
@@ -1,3 +1,25 @@
+Sun Nov  5 05:22:55 2000  Tim Janik  <timj@gtk.org>
+
+       * gsignal.c:
+       fixed a bag full of subtle bugs of immensive screw-up potential in
+       handlers_find(), luckily no one found out about them yet ;)
+       fixed signal_handlers_foreach_matched_R() so it operates on an
+       initial handler list snapshot provided by handlers_find() to work
+       around general reentrancy problems and to avoid multiple callback()
+       invocations on the same handlers.
+       this code is now officially 80% bug free (10% remaining for interface
+       types, and 10% remaining for destroyed signals ;)
+       
+Sat Nov  4 02:01:33 2000  Tim Janik  <timj@gtk.org>
+
+       * gsignal.c (_g_signals_destroy): valid signal nodes start out at 1.
+
+       * gtypeplugin.[hc]: new files holding a GTypePlugin interface
+       implementation that provides the API required by GType to deal with
+       dynamically loadable types.
+
+       * gtype.[hc]: displace any GTypePlugin business to gtypeplugin.h.
+
 Fri Nov  3 07:35:00 2000  Tim Janik  <timj@gtk.org>
 
        * gsignal.[hc]: prefix internal functions with '_'. renamed
index 1507961..4b8e658 100644 (file)
@@ -32,6 +32,7 @@ gobject_public_h_sources = @STRIP_BEGIN@ \
        gparamspecs.h \
        gsignal.h \
        gtype.h \
+       gtypeplugin.h \
        gvalue.h \
        gvaluecollector.h \
        gvaluetypes.h \
@@ -51,6 +52,7 @@ gobject_c_sources = @STRIP_BEGIN@ \
        gparamspecs.c \
        gsignal.c \
        gtype.c \
+       gtypeplugin.c \
        gvalue.c \
        gvaluetypes.c \
 @STRIP_END@
index 7307cbb..c4dd860 100644 (file)
@@ -295,7 +295,7 @@ g_object_do_shutdown (GObject *object)
 static void
 g_object_do_finalize (GObject *object)
 {
-  _g_signal_handlers_destroy (object);
+  g_signal_handlers_destroy (object);
   g_datalist_clear (&object->qdata);
   
 #ifdef DEBUG_OBJECTS
index 051ff8e..841c329 100644 (file)
@@ -73,11 +73,12 @@ g_generic_node_free (GTrashStack **trash_stack_p,
 
 
 /* --- typedefs --- */
-typedef struct _SignalNode  SignalNode;
-typedef struct _SignalKey   SignalKey;
-typedef struct _Emission    Emission;
-typedef struct _Handler     Handler;
-typedef struct _HandlerList HandlerList;
+typedef struct _SignalNode   SignalNode;
+typedef struct _SignalKey    SignalKey;
+typedef struct _Emission     Emission;
+typedef struct _Handler      Handler;
+typedef struct _HandlerList  HandlerList;
+typedef struct _HandlerMatch HandlerMatch;
 typedef enum
 {
   EMISSION_STOP,
@@ -88,47 +89,53 @@ typedef enum
 
 
 /* --- prototypes --- */
-static inline guint             signal_id_lookup      (GQuark           quark,
-                                                      GType            itype);
-static        void              signal_destroy_R      (SignalNode      *signal_node);
-static inline HandlerList*      handler_list_ensure   (guint            signal_id,
-                                                      gpointer         instance);
-static inline HandlerList*      handler_list_lookup   (guint            signal_id,
-                                                      gpointer         instance);
-static inline Handler*          handler_new           (gboolean         after);
-static        void              handler_insert        (guint            signal_id,
-                                                      gpointer         instance,
-                                                      Handler         *handler);
-static        Handler*          handler_lookup        (gpointer         instance,
-                                                      guint            handler_id,
-                                                      guint           *signal_id_p);
-static        Handler*          handler_find          (gpointer         instance,
-                                                      GSignalMatchType mask,
-                                                      guint            signal_id,
-                                                      GQuark           detail,
-                                                      GClosure        *closure,
-                                                      gpointer         func,
-                                                      gpointer         data);
-static inline void              handler_ref           (Handler         *handler);
-static inline void              handler_unref_R       (guint            signal_id,
-                                                      gpointer         instance,
-                                                      Handler         *handler);
-static inline void              emission_push         (Emission       **emission_list_p,
-                                                      guint            signal_id,
-                                                      GQuark           detail,
-                                                      gpointer         instance,
-                                                      EmissionState   *state_p);
-static inline void              emission_pop          (Emission       **emission_list_p,
-                                                      EmissionState   *state_p);
-static inline Emission*         emission_find         (Emission        *emission_list,
-                                                      guint            signal_id,
-                                                      GQuark           detail,
-                                                      gpointer         instance);
-static       void              signal_emit_R         (SignalNode      *node,
-                                                      GQuark           detail,
-                                                      gpointer         instance,
-                                                      GValue          *return_value,
-                                                      const GValue    *instance_and_params);
+static inline guint            signal_id_lookup        (GQuark           quark,
+                                                        GType            itype);
+static       void              signal_destroy_R        (SignalNode      *signal_node);
+static inline HandlerList*     handler_list_ensure     (guint            signal_id,
+                                                        gpointer         instance);
+static inline HandlerList*     handler_list_lookup     (guint            signal_id,
+                                                        gpointer         instance);
+static inline Handler*         handler_new             (gboolean         after);
+static       void              handler_insert          (guint            signal_id,
+                                                        gpointer         instance,
+                                                        Handler         *handler);
+static       Handler*          handler_lookup          (gpointer         instance,
+                                                        guint            handler_id,
+                                                        guint           *signal_id_p);
+static inline HandlerMatch*    handler_match_prepend   (HandlerMatch    *list,
+                                                        Handler         *handler,
+                                                        guint            signal_id);
+static inline HandlerMatch*    handler_match_free1_R   (HandlerMatch    *node,
+                                                        gpointer         instance);
+static       HandlerMatch*     handlers_find           (gpointer         instance,
+                                                        GSignalMatchType mask,
+                                                        guint            signal_id,
+                                                        GQuark           detail,
+                                                        GClosure        *closure,
+                                                        gpointer         func,
+                                                        gpointer         data,
+                                                        gboolean         one_and_only);
+static inline void             handler_ref             (Handler         *handler);
+static inline void             handler_unref_R         (guint            signal_id,
+                                                        gpointer         instance,
+                                                        Handler         *handler);
+static inline void             emission_push           (Emission       **emission_list_p,
+                                                        guint            signal_id,
+                                                        GQuark           detail,
+                                                        gpointer         instance,
+                                                        EmissionState   *state_p);
+static inline void             emission_pop            (Emission       **emission_list_p,
+                                                        EmissionState   *state_p);
+static inline Emission*                emission_find           (Emission        *emission_list,
+                                                        guint            signal_id,
+                                                        GQuark           detail,
+                                                        gpointer         instance);
+static       void              signal_emit_R           (SignalNode      *node,
+                                                        GQuark           detail,
+                                                        gpointer         instance,
+                                                        GValue          *return_value,
+                                                        const GValue    *instance_and_params);
 
 
 /* --- structures --- */
@@ -172,7 +179,6 @@ struct _HandlerList
   guint    signal_id;
   Handler *handlers;
 };
-
 struct _Handler
 {
   guint         id;
@@ -186,6 +192,15 @@ struct _Handler
   guint         after : 1;
   GClosure     *closure;
 };
+struct _HandlerMatch
+{
+  Handler      *handler;
+  HandlerMatch *next;
+  union {
+    guint       signal_id;
+    gpointer   dummy;
+  } d;
+};
 
 
 /* --- variables --- */
@@ -313,15 +328,50 @@ handler_lookup (gpointer instance,
   return NULL;
 }
 
-static Handler*
-handler_find (gpointer         instance,
-             GSignalMatchType mask,
-             guint            signal_id,
-             GQuark           detail,
-             GClosure        *closure,
-             gpointer         func,
-             gpointer         data)
+static inline HandlerMatch*
+handler_match_prepend (HandlerMatch *list,
+                      Handler      *handler,
+                      guint         signal_id)
+{
+  HandlerMatch *node;
+  
+  /* yeah, we could use our own memchunk here, introducing yet more
+   * rarely used cached nodes and extra allocation overhead.
+   * instead, we use GList* nodes, since they are exactly the size
+   * we need and are already cached. g_signal_init() asserts this.
+   */
+  node = (HandlerMatch*) g_list_alloc ();
+  node->handler = handler;
+  node->next = list;
+  node->d.signal_id = signal_id;
+  handler_ref (handler);
+  
+  return node;
+}
+static inline HandlerMatch*
+handler_match_free1_R (HandlerMatch *node,
+                      gpointer      instance)
+{
+  HandlerMatch *next = node->next;
+  
+  handler_unref_R (node->d.signal_id, instance, node->handler);
+  g_list_free_1 ((GList*) node);
+  
+  return next;
+}
+
+static HandlerMatch*
+handlers_find (gpointer         instance,
+              GSignalMatchType mask,
+              guint            signal_id,
+              GQuark           detail,
+              GClosure        *closure,
+              gpointer         func,
+              gpointer         data,
+              gboolean         one_and_only)
 {
+  HandlerMatch *mlist = NULL;
+  
   if (mask & G_SIGNAL_MATCH_ID)
     {
       HandlerList *hlist = handler_list_lookup (signal_id, instance);
@@ -334,17 +384,22 @@ handler_find (gpointer         instance,
          if (!node || !node->c_marshaller)
            return NULL;
        }
-         
+      
       mask = ~mask;
       for (handler = hlist ? hlist->handlers : NULL; handler; handler = handler->next)
-        if (((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
+        if (handler->id &&
+           ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
            ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
             ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
            ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
            ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
                                              handler->closure->meta_marshal == 0 &&
                                              ((GCClosure*) handler->closure)->callback == func)))
-         return handler;
+         {
+           mlist = handler_match_prepend (mlist, handler, signal_id);
+           if (one_and_only)
+             return mlist;
+         }
     }
   else
     {
@@ -367,21 +422,26 @@ handler_find (gpointer         instance,
                  if (!node->c_marshaller)
                    continue;
                }
-
+             
               for (handler = hlist->handlers; handler; handler = handler->next)
-               if (((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
+               if (handler->id &&
+                   ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
                     ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
                     ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
                    ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
                    ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
                                                      handler->closure->meta_marshal == 0 &&
                                                      ((GCClosure*) handler->closure)->callback == func)))
-                 return handler;
+                 {
+                   mlist = handler_match_prepend (mlist, handler, signal_id);
+                   if (one_and_only)
+                     return mlist;
+                 }
             }
         }
     }
   
-  return NULL;
+  return mlist;
 }
 
 static inline Handler*
@@ -433,7 +493,7 @@ handler_unref_R (guint    signal_id,
     {
       if (handler->next)
         handler->next->prev = handler->prev;
-      if (handler->prev)       /* watch out for _g_signal_handlers_destroy()! */
+      if (handler->prev)       /* watch out for g_signal_handlers_destroy()! */
         handler->prev->next = handler->next;
       else
         {
@@ -507,7 +567,7 @@ emission_pop (Emission     **emission_list_p,
              EmissionState *state_p)
 {
   Emission **loc = emission_list_p, *emission = *loc;
-
+  
   while (emission->state_p != state_p)
     {
       loc = &emission->next;
@@ -551,6 +611,9 @@ g_signal_init (void) /* sync with gtype.c */
   G_LOCK (g_signal_mutex);
   if (!g_n_signal_nodes)
     {
+      /* handler_id_node_prepend() requires this */
+      g_assert (sizeof (GList) == sizeof (HandlerMatch));
+      
       /* setup signal key array */
       g_signal_key_bsa.cmp_func = signal_key_cmp;
       g_signal_key_bsa.sizeof_node = sizeof (SignalKey);
@@ -573,7 +636,7 @@ _g_signals_destroy (GType itype)
   guint i;
   
   G_LOCK (g_signal_mutex);
-  for (i = 0; i < g_n_signal_nodes; i++)
+  for (i = 1; i < g_n_signal_nodes; i++)
     {
       SignalNode *node = g_signal_nodes[i];
       
@@ -683,21 +746,21 @@ g_signal_parse_name (const gchar *detailed_signal,
 {
   GQuark detail = 0;
   guint signal_id;
-
+  
   g_return_val_if_fail (detailed_signal != NULL, FALSE);
   g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), FALSE);
-
+  
   G_LOCK (g_signal_mutex);
   signal_id = signal_parse_name (detailed_signal, itype, &detail, force_detail_quark);
   G_UNLOCK (g_signal_mutex);
-
+  
   if (signal_id)
     {
       if (signal_id_p)
        *signal_id_p = signal_id;
       if (detail_p)
        *detail_p = detail;
-
+      
       return TRUE;
     }
   else
@@ -725,7 +788,7 @@ g_signal_name (guint signal_id)
 {
   SignalNode *node;
   gchar *name;
-
+  
   G_LOCK (g_signal_mutex);
   node = LOOKUP_SIGNAL_NODE (signal_id);
   name = node ? node->name : NULL;
@@ -739,9 +802,9 @@ g_signal_query (guint         signal_id,
                GSignalQuery *query)
 {
   SignalNode *node;
-
+  
   g_return_if_fail (query != NULL);
-
+  
   G_LOCK (g_signal_mutex);
   node = LOOKUP_SIGNAL_NODE (signal_id);
   if (!node || node->destroyed)
@@ -767,12 +830,12 @@ g_signal_list_ids (GType  itype,
   GArray *result;
   guint n_nodes;
   guint i;
-
+  
   g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), NULL);
   g_return_val_if_fail (n_ids != NULL, NULL);
-
+  
   G_LOCK (g_signal_mutex);
-
+  
   keys = g_signal_key_bsa.nodes;
   n_nodes  = g_signal_key_bsa.n_nodes;
   result = g_array_new (FALSE, FALSE, sizeof (guint));
@@ -781,16 +844,16 @@ g_signal_list_ids (GType  itype,
     if (keys[i].itype == itype)
       {
        gchar *name = g_quark_to_string (keys[i].quark);
-
+       
        /* Signal names with "_" in them are aliases to the same
         * name with "-" instead of "_".
         */
        if (!strchr (name, '_'))
          g_array_append_val (result, keys[i].signal_id);
       }
-
+  
   *n_ids = result->len;
-
+  
   G_UNLOCK (g_signal_mutex);
   
   return (guint *) g_array_free (result, FALSE);
@@ -1056,7 +1119,7 @@ g_signal_handler_disconnect (gpointer instance,
 }
 
 void
-_g_signal_handlers_destroy (gpointer instance)
+g_signal_handlers_destroy (gpointer instance)
 {
   GBSearchArray *hlbsa;
   
@@ -1070,7 +1133,7 @@ _g_signal_handlers_destroy (gpointer instance)
       
       /* reentrancy caution, delete instance trace first */
       g_hash_table_remove (g_handler_list_bsa_ht, instance);
-
+      
       for (i = 0; i < hlbsa->n_nodes; i++)
         {
           HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
@@ -1107,48 +1170,52 @@ g_signal_handler_find (gpointer         instance,
                        gpointer         func,
                        gpointer         data)
 {
-  Handler *handler;
   guint handler_id = 0;
   
   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
   g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
-
+  
   if (mask & G_SIGNAL_MATCH_MASK)
     {
+      HandlerMatch *mlist;
+      
       G_LOCK (g_signal_mutex);
-      handler = handler_find (instance, mask, signal_id, detail, closure, func, data);
-      handler_id = handler ? handler->id : 0;
+      mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, TRUE);
+      if (mlist)
+       {
+         handler_id = mlist->handler->id;
+         handler_match_free1_R (mlist, instance);
+       }
       G_UNLOCK (g_signal_mutex);
     }
-
+  
   return handler_id;
 }
 
 static guint
-signal_handlers_foreach_matched (gpointer         instance,
-                                GSignalMatchType mask,
-                                guint            signal_id,
-                                GQuark           detail,
-                                GClosure        *closure,
-                                gpointer         func,
-                                gpointer         data,
-                                void           (*callback) (gpointer instance,
-                                                            guint    handler_id))
+signal_handlers_foreach_matched_R (gpointer         instance,
+                                  GSignalMatchType mask,
+                                  guint            signal_id,
+                                  GQuark           detail,
+                                  GClosure        *closure,
+                                  gpointer         func,
+                                  gpointer         data,
+                                  void           (*callback) (gpointer instance,
+                                                              guint    handler_id))
 {
-  Handler *handler;
+  HandlerMatch *mlist;
   guint n_handlers = 0;
-
-  handler = handler_find (instance, mask, signal_id, detail, closure, func, data);
-  while (handler && handler->id)
+  
+  mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, FALSE);
+  while (mlist)
     {
       n_handlers++;
       G_UNLOCK (g_signal_mutex);
-      callback (instance, handler->id);
+      callback (instance, mlist->handler->id);
       G_LOCK (g_signal_mutex);
-      /* need constant relookups due to callback */
-      handler = handler_find (instance, mask, signal_id, detail, closure, func, data);
+      mlist = handler_match_free1_R (mlist, instance);
     }
-
+  
   return n_handlers;
 }
 
@@ -1162,19 +1229,19 @@ g_signal_handlers_block_matched (gpointer         instance,
                                 gpointer         data)
 {
   guint n_handlers = 0;
-
+  
   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
   g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE);
-
+  
   if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
     {
       G_LOCK (g_signal_mutex);
-      n_handlers = signal_handlers_foreach_matched (instance, mask, signal_id, detail,
-                                                   closure, func, data,
-                                                   g_signal_handler_block);
+      n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
+                                                     closure, func, data,
+                                                     g_signal_handler_block);
       G_UNLOCK (g_signal_mutex);
     }
-
+  
   return n_handlers;
 }
 
@@ -1195,12 +1262,12 @@ g_signal_handlers_unblock_matched (gpointer         instance,
   if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
     {
       G_LOCK (g_signal_mutex);
-      n_handlers = signal_handlers_foreach_matched (instance, mask, signal_id, detail,
-                                                   closure, func, data,
-                                                   g_signal_handler_unblock);
+      n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
+                                                     closure, func, data,
+                                                     g_signal_handler_unblock);
       G_UNLOCK (g_signal_mutex);
     }
-
+  
   return n_handlers;
 }
 
@@ -1214,19 +1281,19 @@ g_signal_handlers_disconnect_matched (gpointer         instance,
                                      gpointer         data)
 {
   guint n_handlers = 0;
-
+  
   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
   g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE);
-
+  
   if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
     {
       G_LOCK (g_signal_mutex);
-      n_handlers = signal_handlers_foreach_matched (instance, mask, signal_id, detail,
-                                                   closure, func, data,
-                                                   g_signal_handler_disconnect);
+      n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
+                                                     closure, func, data,
+                                                     g_signal_handler_disconnect);
       G_UNLOCK (g_signal_mutex);
     }
-
+  
   return n_handlers;
 }
 
@@ -1236,7 +1303,8 @@ g_signal_has_handler_pending (gpointer instance,
                              GQuark   detail,
                              gboolean may_be_blocked)
 {
-  Handler *handler = NULL;
+  HandlerMatch *mlist;
+  gboolean has_pending;
   
   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
   g_return_val_if_fail (signal_id > 0, FALSE);
@@ -1253,13 +1321,19 @@ g_signal_has_handler_pending (gpointer instance,
          return FALSE;
        }
     }
-  handler = handler_find (instance,
-                         (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL |
-                          (may_be_blocked ? 0 : G_SIGNAL_MATCH_UNBLOCKED)),
-                         signal_id, detail, NULL, NULL, NULL);
+  mlist = handlers_find (instance,
+                        (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | (may_be_blocked ? 0 : G_SIGNAL_MATCH_UNBLOCKED)),
+                        signal_id, detail, NULL, NULL, NULL, TRUE);
+  if (mlist)
+    {
+      has_pending = TRUE;
+      handler_match_free1_R (mlist, instance);
+    }
+  else
+    has_pending = FALSE;
   G_UNLOCK (g_signal_mutex);
   
-  return handler != NULL;
+  return has_pending;
 }
 
 void
@@ -1277,7 +1351,7 @@ g_signal_emitv (const GValue *instance_and_params,
   instance = g_value_get_as_pointer (instance_and_params);
   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
   g_return_if_fail (signal_id > 0);
-
+  
   param_values = instance_and_params + 1;
   
   G_LOCK (g_signal_mutex);
index 7c2caa0..9d2c5ca 100644 (file)
@@ -169,7 +169,7 @@ gboolean g_signal_parse_name                      (const gchar       *detailed_signal,
                                               guint             *signal_id_p,
                                               GQuark            *detail_p,
                                               gboolean           force_detail_quark);
-void    _g_signal_handlers_destroy           (gpointer           instance);
+void    g_signal_handlers_destroy            (gpointer           instance);
 void    _g_signals_destroy                   (GType              itype);
 
 
index 5b055b3..a288b65 100644 (file)
@@ -18,6 +18,7 @@
  */
 #include       "gtype.h"
 
+#include       "gtypeplugin.h"
 #include       <string.h>
 
 #define FIXME_DISABLE_PREALLOCATIONS
                                    G_TYPE_FLAG_DEEP_DERIVABLE)
 #define        TYPE_FLAG_MASK             (G_TYPE_FLAG_ABSTRACT)
 
-#define        g_type_plugin_ref(p)                            ((p)->vtable->plugin_ref (p))
-#define g_type_plugin_unref(p)                         ((p)->vtable->plugin_unref (p))
-#define        g_type_plugin_complete_type_info(p,t,i,v)       ((p)->vtable->complete_type_info ((p), (t), (i), (v)))
-#define        g_type_plugin_complete_interface_info(p,f,t,i)  ((p)->vtable->complete_interface_info ((p), (f), (t), (i)))
 
 
 /* --- typedefs --- */
@@ -398,31 +395,19 @@ check_plugin (GTypePlugin *plugin,
                 type_name);
       return FALSE;
     }
-  if (!plugin->vtable)
+  if (!G_IS_TYPE_PLUGIN (plugin))
     {
-      g_warning ("plugin for type `%s' has no function table",
-                type_name);
-      return FALSE;
-    }
-  if (!plugin->vtable->plugin_ref)
-    {
-      g_warning ("plugin for type `%s' has no plugin_ref() implementation",
-                type_name);
+      g_warning ("plugin pointer (%p) for type `%s' is invalid",
+                plugin, type_name);
       return FALSE;
     }
-  if (!plugin->vtable->plugin_unref)
-    {
-      g_warning ("plugin for type `%s' has no plugin_unref() implementation",
-                type_name);
-      return FALSE;
-    }
-  if (need_complete_type_info && !plugin->vtable->complete_type_info)
+  if (need_complete_type_info && !G_TYPE_PLUGIN_GET_CLASS (plugin)->complete_type_info)
     {
       g_warning ("plugin for type `%s' has no complete_type_info() implementation",
                 type_name);
       return FALSE;
     }
-  if (need_complete_interface_info && !plugin->vtable->complete_interface_info)
+  if (need_complete_interface_info && !G_TYPE_PLUGIN_GET_CLASS (plugin)->complete_interface_info)
     {
       g_warning ("plugin for type `%s' has no complete_interface_info() implementation",
                 type_name);
@@ -830,7 +815,7 @@ type_data_ref (TypeNode *node)
       
       memset (&tmp_info, 0, sizeof (tmp_info));
       memset (&tmp_value_table, 0, sizeof (tmp_value_table));
-      g_type_plugin_ref (node->plugin);
+      g_type_plugin_use (node->plugin);
       g_type_plugin_complete_type_info (node->plugin, NODE_TYPE (node), &tmp_info, &tmp_value_table);
       check_type_info (pnode, G_TYPE_FUNDAMENTAL (NODE_TYPE (node)), NODE_NAME (node), &tmp_info);
       type_data_make (node, &tmp_info,
@@ -930,7 +915,7 @@ type_iface_retrive_holder_info (TypeNode *iface,
       type_data_ref (iface);
 
       memset (&tmp_info, 0, sizeof (tmp_info));
-      g_type_plugin_ref (iholder->plugin);
+      g_type_plugin_use (iholder->plugin);
       g_type_plugin_complete_interface_info (iholder->plugin, NODE_TYPE (iface), instance_type, &tmp_info);
       check_interface_info (iface, instance_type, &tmp_info);
       iholder->info = g_memdup (&tmp_info, sizeof (tmp_info));
@@ -954,7 +939,7 @@ type_iface_blow_holder_info (TypeNode *iface,
     {
       g_free (iholder->info);
       iholder->info = NULL;
-      g_type_plugin_unref (iholder->plugin);
+      g_type_plugin_unuse (iholder->plugin);
 
       type_data_unref (iface, FALSE);
     }
@@ -1279,7 +1264,7 @@ type_data_last_unref (GType    type,
       
       if (ptype)
        type_data_unref (LOOKUP_TYPE_NODE (ptype), FALSE);
-      g_type_plugin_unref (node->plugin);
+      g_type_plugin_unuse (node->plugin);
     }
 }
 
@@ -2117,6 +2102,10 @@ g_type_init (void)
   type_data_make (node, &info, NULL); /* FIXME */
   g_assert (type == G_TYPE_INTERFACE);
 
+  /* G_TYPE_TYPE_PLUGIN
+   */
+  g_type_plugin_get_type ();
+
   /* G_TYPE_* value types
    */
   g_value_types_init ();
index 1c8e0b4..bbef767 100644 (file)
@@ -116,7 +116,6 @@ typedef guint32                         GType;
 typedef struct _GValue                  GValue;
 typedef union  _GTypeCValue             GTypeCValue;
 typedef struct _GTypePlugin             GTypePlugin;
-typedef struct _GTypePluginVTable       GTypePluginVTable;
 typedef struct _GTypeClass              GTypeClass;
 typedef struct _GTypeInterface          GTypeInterface;
 typedef struct _GTypeInstance           GTypeInstance;
@@ -154,7 +153,7 @@ struct _GTypeInterface
 #define G_TYPE_CHECK_INSTANCE(instance)                                (_G_TYPE_CHI ((GTypeInstance*) (instance)))
 #define G_TYPE_CHECK_INSTANCE_CAST(instance, g_type, c_type)    (_G_TYPE_CIC ((instance), (g_type), c_type))
 #define G_TYPE_CHECK_INSTANCE_TYPE(instance, g_type)            (_G_TYPE_CIT ((instance), (g_type)))
-#define G_TYPE_INSTANCE_GET_CLASS(instance, g_type, c_type)     (_G_TYPE_IGC ((instance), c_type))
+#define G_TYPE_INSTANCE_GET_CLASS(instance, g_type, c_type)     (_G_TYPE_IGC ((instance), (g_type), c_type))
 #define G_TYPE_INSTANCE_GET_INTERFACE(instance, g_type, c_type) (_G_TYPE_IGI ((instance), (g_type), c_type))
 #define G_TYPE_CHECK_CLASS_CAST(g_class, g_type, c_type)        (_G_TYPE_CCC ((g_class), (g_type), c_type))
 #define G_TYPE_CHECK_CLASS_TYPE(g_class, g_type)                (_G_TYPE_CCT ((g_class), (g_type)))
@@ -210,29 +209,8 @@ typedef void   (*GInterfaceInitFunc)         (gpointer         g_iface,
                                              gpointer         iface_data);
 typedef void   (*GInterfaceFinalizeFunc)     (gpointer         g_iface,
                                              gpointer         iface_data);
-typedef void (*GTypePluginRef)               (GTypePlugin     *plugin);
-typedef void (*GTypePluginUnRef)             (GTypePlugin     *plugin);
-typedef void (*GTypePluginFillTypeInfo)      (GTypePlugin     *plugin,
-                                              GType            g_type,
-                                              GTypeInfo       *info,
-                                             GTypeValueTable *value_table);
-typedef void (*GTypePluginFillInterfaceInfo) (GTypePlugin     *plugin,
-                                              GType            interface_type,
-                                              GType            instance_type,
-                                              GInterfaceInfo  *info);
 typedef gboolean (*GTypeClassCacheFunc)             (gpointer         cache_data,
                                              GTypeClass      *g_class);
-struct _GTypePlugin
-{
-  GTypePluginVTable     *vtable;
-};
-struct _GTypePluginVTable
-{
-  GTypePluginRef                plugin_ref;
-  GTypePluginUnRef              plugin_unref;
-  GTypePluginFillTypeInfo       complete_type_info;
-  GTypePluginFillInterfaceInfo  complete_interface_info;
-};
 typedef enum    /*< skip >*/
 {
   G_TYPE_FLAG_CLASSED           = (1 << 0),
@@ -359,7 +337,7 @@ GTypeValueTable* g_type_value_table_peek        (GType                   type);
 #define _G_TYPE_CCT(cp, gt)             (g_type_class_is_a ((GTypeClass*) cp, gt))
 #define _G_TYPE_CVT(vl, gt)             (g_type_value_conforms_to ((GValue*) vl, gt))
 #define _G_TYPE_CHV(vl)                        (g_type_check_value ((GValue*) vl))
-#define _G_TYPE_IGC(ip, ct)             ((ct*) (((GTypeInstance*) ip)->g_class))
+#define _G_TYPE_IGC(ip, gt, ct)         ((ct*) (((GTypeInstance*) ip)->g_class))
 #define _G_TYPE_IGI(ip, gt, ct)         ((ct*) g_type_interface_peek (((GTypeInstance*) ip)->g_class, gt))
 
 
diff --git a/gobject/gtypeplugin.c b/gobject/gtypeplugin.c
new file mode 100644 (file)
index 0000000..51da5d8
--- /dev/null
@@ -0,0 +1,100 @@
+/* GObject - GLib Type, Object, Parameter and Signal Library
+ * Copyright (C) 2000 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include       "gtypeplugin.h"
+
+
+
+/* --- functions --- */
+GType
+g_type_plugin_get_type (void)
+{
+  static GType type_plugin_type = 0;
+  
+  if (!type_plugin_type)
+    {
+      static const GTypeInfo type_plugin_info = {
+       sizeof (GTypePluginClass),
+       NULL,           /* base_init */
+       NULL,           /* base_finalize */
+      };
+      
+      type_plugin_type = g_type_register_static (G_TYPE_INTERFACE, "GTypePlugin", &type_plugin_info, 0);
+    }
+  
+  return type_plugin_type;
+}
+
+void
+g_type_plugin_use (GTypePlugin *plugin)
+{
+  GTypePluginClass *iface;
+  
+  g_return_if_fail (G_IS_TYPE_PLUGIN (plugin));
+  
+  iface = G_TYPE_PLUGIN_GET_CLASS (plugin);
+  iface->use_plugin (plugin);
+}
+
+void
+g_type_plugin_unuse (GTypePlugin *plugin)
+{
+  GTypePluginClass *iface;
+  
+  g_return_if_fail (G_IS_TYPE_PLUGIN (plugin));
+  
+  iface = G_TYPE_PLUGIN_GET_CLASS (plugin);
+  iface->unuse_plugin (plugin);
+}
+
+void
+g_type_plugin_complete_type_info (GTypePlugin     *plugin,
+                                 GType            g_type,
+                                 GTypeInfo       *info,
+                                 GTypeValueTable *value_table)
+{
+  GTypePluginClass *iface;
+  
+  g_return_if_fail (G_IS_TYPE_PLUGIN (plugin));
+  g_return_if_fail (info != NULL);
+  g_return_if_fail (value_table != NULL);
+  
+  iface = G_TYPE_PLUGIN_GET_CLASS (plugin);
+  iface->complete_type_info (plugin,
+                            g_type,
+                            info,
+                            value_table);
+}
+
+void
+g_type_plugin_complete_interface_info (GTypePlugin    *plugin,
+                                      GType           interface_type,
+                                      GType           instance_type,
+                                      GInterfaceInfo *info)
+{
+  GTypePluginClass *iface;
+  
+  g_return_if_fail (G_IS_TYPE_PLUGIN (plugin));
+  g_return_if_fail (info != NULL);
+  
+  iface = G_TYPE_PLUGIN_GET_CLASS (plugin);
+  iface->complete_interface_info (plugin,
+                                 interface_type,
+                                 instance_type,
+                                 info);
+}
diff --git a/gobject/gtypeplugin.h b/gobject/gtypeplugin.h
new file mode 100644 (file)
index 0000000..380dd32
--- /dev/null
@@ -0,0 +1,85 @@
+/* GObject - GLib Type, Object, Parameter and Signal Library
+ * Copyright (C) 2000 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __G_TYPE_PLUGIN_H__
+#define __G_TYPE_PLUGIN_H__
+
+
+#include       <gobject/gtype.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+
+/* --- type macros --- */
+#define G_TYPE_TYPE_PLUGIN             (g_type_plugin_get_type ())
+#define G_TYPE_PLUGIN(inst)            (G_TYPE_CHECK_INSTANCE_CAST ((inst), G_TYPE_TYPE_PLUGIN, GTypePlugin))
+#define G_TYPE_PLUGIN_CLASS(vtable)    (G_TYPE_CHECK_CLASS_CAST ((vtable), G_TYPE_TYPE_PLUGIN, GTypePluginClass))
+#define G_IS_TYPE_PLUGIN(inst)         (G_TYPE_CHECK_INSTANCE_TYPE ((inst), G_TYPE_TYPE_PLUGIN))
+#define G_IS_TYPE_PLUGIN_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), G_TYPE_TYPE_PLUGIN))
+#define G_TYPE_PLUGIN_GET_CLASS(inst)  (G_TYPE_INSTANCE_GET_INTERFACE ((inst), G_TYPE_TYPE_PLUGIN, GTypePluginClass))
+
+
+/* --- typedefs & structures --- */
+typedef struct _GTypePluginClass                  GTypePluginClass;
+typedef void  (*GTypePluginUse)                          (GTypePlugin     *plugin);
+typedef void  (*GTypePluginUnuse)                (GTypePlugin     *plugin);
+typedef void  (*GTypePluginCompleteTypeInfo)     (GTypePlugin     *plugin,
+                                                  GType            g_type,
+                                                  GTypeInfo       *info,
+                                                  GTypeValueTable *value_table);
+typedef void  (*GTypePluginCompleteInterfaceInfo) (GTypePlugin     *plugin,
+                                                  GType            interface_type,
+                                                  GType            instance_type,
+                                                  GInterfaceInfo  *info);
+struct _GTypePluginClass
+{
+  GTypeInterface                  base_iface;
+  
+  GTypePluginUse                  use_plugin;
+  GTypePluginUnuse                unuse_plugin;
+  GTypePluginCompleteTypeInfo     complete_type_info;
+  GTypePluginCompleteInterfaceInfo complete_interface_info;
+};
+
+
+/* --- prototypes --- */
+GType  g_type_plugin_get_type                  (void)  G_GNUC_CONST;
+void   g_type_plugin_use                       (GTypePlugin     *plugin);
+void   g_type_plugin_unuse                     (GTypePlugin     *plugin);
+void   g_type_plugin_complete_type_info        (GTypePlugin     *plugin,
+                                                GType            g_type,
+                                                GTypeInfo       *info,
+                                                GTypeValueTable *value_table);
+void   g_type_plugin_complete_interface_info   (GTypePlugin     *plugin,
+                                                GType            interface_type,
+                                                GType            instance_type,
+                                                GInterfaceInfo  *info);
+
+
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __G_TYPE_PLUGIN_H__ */