adapt to work with new CVS gtk-doc, leaving the old rules in place caused
authorTim Janik <timj@gtk.org>
Wed, 31 Jan 2001 06:27:41 +0000 (06:27 +0000)
committerTim Janik <timj@src.gnome.org>
Wed, 31 Jan 2001 06:27:41 +0000 (06:27 +0000)
Wed Jan 31 07:14:22 2001  Tim Janik  <timj@gtk.org>

        * gobject/Makefile.am: adapt to work with new CVS gtk-doc, leaving the old
        rules in place caused bogus recursions. main changes:
        - add to conditionalized section:
          all-local:
                $(MAKE) scan
                $(MAKE) templates
                $(MAKE) sgml
                $(MAKE) html.stamp
          html.stamp: sgml.stamp $(EXTRA_SGML_FILES)
                $(MAKE) html
          DOC_STAMPS= html.stamp sgml.stamp
        - change:
          maintainer-clean-local: clean
          -     cd $(srcdir) && rm -rf sgml html $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt
          +     cd $(srcdir) && rm -rf sgml html $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt $(DOC_STAMPS)

        * glib/Makefile.am (maintainer-clean-local): dito.

Wed Jan 31 06:21:32 2001  Tim Janik  <timj@gtk.org>

        * gobject/tmpl/types.sgml: applied docu patch from Eric Lemings
        <eric.b.lemings@lmco.com>, did some more editing.

Wed Jan 31 06:19:49 2001  Tim Janik  <timj@gtk.org>

        * gparam.h: gtk-doc sucks for not dealing with #define inside enums.

        * gtype.[hc]: added G_TYPE_FLAG_RESERVED_ID_BIT, a bit in the type
        number that's supposed to be left untouched (preserved mainly
        for the signal code).

        * *.c: added thread safety code, based on an old patch from sebastian.
        the remaining thread safety issues are now datalists on pspecs (to be
        solved im gdataset.c) and gvalue.c where locking concerns value exchange
        functionality only, and that's soon to be revised.

20 files changed:
docs/reference/ChangeLog
docs/reference/glib/Makefile.am
docs/reference/gobject/Makefile.am
docs/reference/gobject/gobject-sections.txt
docs/reference/gobject/tmpl/closures.sgml
docs/reference/gobject/tmpl/param_specs.sgml
docs/reference/gobject/tmpl/types.sgml
docs/reference/gobject/tmpl/value_types.sgml
gobject/ChangeLog
gobject/gclosure.c
gobject/genums.c
gobject/gobject.c
gobject/gparam.c
gobject/gparam.h
gobject/gparamspecs.c
gobject/gsignal.c
gobject/gtype.c
gobject/gtype.h
gobject/gvalue.c
gobject/gvaluetypes.c

index a7f1e44..a385889 100644 (file)
@@ -1,7 +1,32 @@
+Wed Jan 31 07:14:22 2001  Tim Janik  <timj@gtk.org>
+
+       * gobject/Makefile.am: adapt to work with new CVS gtk-doc, leaving the old
+       rules in place caused bogus recursions. main changes:
+       - add to conditionalized section:
+         all-local:
+               $(MAKE) scan
+               $(MAKE) templates
+               $(MAKE) sgml
+               $(MAKE) html.stamp
+         html.stamp: sgml.stamp $(EXTRA_SGML_FILES)
+               $(MAKE) html
+         DOC_STAMPS= html.stamp sgml.stamp
+       - change:
+         maintainer-clean-local: clean
+         -     cd $(srcdir) && rm -rf sgml html $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt
+         +     cd $(srcdir) && rm -rf sgml html $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt $(DOC_STAMPS)
+
+       * glib/Makefile.am (maintainer-clean-local): dito.
+
+Wed Jan 31 06:21:32 2001  Tim Janik  <timj@gtk.org>
+
+       * gobject/tmpl/types.sgml: applied docu patch from Eric Lemings
+       <eric.b.lemings@lmco.com>, did some more editing.
+
 2001-01-30  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
 
        * glib/glib-sections.txt, glib/tmpl/threads.sgml: Added
-       g_static_mutex_free
+       g_static_mutex_free().
 
 Tue Jan  9 03:10:38 2001  Tim Janik  <timj@gtk.org>
 
index a683112..72d66c5 100644 (file)
@@ -96,19 +96,28 @@ EXTRA_DIST =                                \
        $(DOC_MODULE)-overrides.txt
 
 if ENABLE_GTK_DOC
-all-local: html/index.html
-
-$(DOC_MODULE)-decl.txt: 
+all-local:
        $(MAKE) scan
-
-$(tmpl_sources): $(DOC_MODULE)-decl.txt $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt
        $(MAKE) templates
-
-sgml/$(DOC_MODULE)-doc.bottom: $(tmpl_sources) $(DOC_MODULE)-decl.txt
        $(MAKE) sgml
-
-html/index.html: sgml/$(DOC_MODULE)-doc.bottom $(DOC_MAIN_SGML_FILE)
+       $(MAKE) html.stamp
+html.stamp: sgml.stamp $(EXTRA_SGML_FILES)
        $(MAKE) html
+DOC_STAMPS= html.stamp sgml.stamp
+
+#all-local: html/index.html
+#
+#$(DOC_MODULE)-decl.txt: 
+#      $(MAKE) scan
+#
+#$(tmpl_sources): $(DOC_MODULE)-decl.txt $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt
+#      $(MAKE) templates
+#
+#sgml/$(DOC_MODULE)-doc.bottom: $(tmpl_sources) $(DOC_MODULE)-decl.txt
+#      $(MAKE) sgml
+#
+#html/index.html: sgml/$(DOC_MODULE)-doc.bottom $(DOC_MAIN_SGML_FILE)
+#      $(MAKE) html
 endif
 
 scan:
@@ -133,7 +142,7 @@ clean-local:
        rm -f *~ *.bak *.signals *-unused.txt
 
 maintainer-clean-local: clean
-       cd $(srcdir) && rm -rf sgml html $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt
+       cd $(srcdir) && rm -rf sgml html $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt $(DOC_STAMPS)
 
 install-data-local:
        $(mkinstalldirs) $(DESTDIR)$(TARGET_DIR)
index 855cb56..d256997 100644 (file)
@@ -45,19 +45,28 @@ EXTRA_DIST =                                \
        $(DOC_MODULE)-overrides.txt
 
 if ENABLE_GTK_DOC
-all-local: html/index.html
-
-$(DOC_MODULE)-decl.txt: 
+all-local:
        $(MAKE) scan
-
-$(tmpl_sources): $(DOC_MODULE)-decl.txt $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt
        $(MAKE) templates
-
-sgml/$(DOC_MODULE)-doc.bottom: $(tmpl_sources) $(DOC_MODULE)-decl.txt
        $(MAKE) sgml
-
-html/index.html: sgml/$(DOC_MODULE)-doc.bottom $(DOC_MAIN_SGML_FILE)
+       $(MAKE) html.stamp
+html.stamp: sgml.stamp $(EXTRA_SGML_FILES)
        $(MAKE) html
+DOC_STAMPS= html.stamp sgml.stamp
+
+#all-local: html/index.html
+#
+#$(DOC_MODULE)-decl.txt: 
+#      $(MAKE) scan
+#
+#$(tmpl_sources): $(DOC_MODULE)-decl.txt $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt
+#      $(MAKE) templates
+#
+#sgml/$(DOC_MODULE)-doc.bottom: $(tmpl_sources) $(DOC_MODULE)-decl.txt
+#      $(MAKE) sgml
+#
+#html/index.html: sgml/$(DOC_MODULE)-doc.bottom $(DOC_MAIN_SGML_FILE)
+#      $(MAKE) html
 endif
 
 scan:
@@ -81,7 +90,7 @@ clean-local:
        rm -f *~ *.bak *.signals *-unused.txt
 
 maintainer-clean-local: clean
-       cd $(srcdir) && rm -rf sgml html $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt
+       cd $(srcdir) && rm -rf sgml html $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt $(DOC_STAMPS)
 
 install-data-local:
        $(mkinstalldirs) $(DESTDIR)$(TARGET_DIR)
index 80e6c13..5c31068 100644 (file)
@@ -39,6 +39,7 @@ G_TYPE_CHECK_CLASS_CAST
 G_TYPE_CHECK_CLASS_TYPE
 G_TYPE_CHECK_VALUE
 G_TYPE_CHECK_VALUE_TYPE
+G_TYPE_FLAG_RESERVED_ID_BIT
 g_type_init
 g_type_name
 g_type_qname
@@ -300,6 +301,7 @@ g_value_dup_param
 g_value_get_ccallback
 g_value_get_pointer
 g_value_set_pointer
+g_value_get_as_pointer
 g_value_set_ccallback
 g_value_set_instance
 </SECTION>
@@ -316,6 +318,9 @@ G_IS_PARAM_SPEC
 G_PARAM_SPEC_GET_CLASS
 G_PARAM_SPEC_VALUE_TYPE
 G_TYPE_IS_PARAM
+G_PARAM_READWRITE
+G_PARAM_MASK
+G_PARAM_USER_SHIFT
 GParamFlags
 g_param_spec_ref
 g_param_spec_unref
@@ -328,12 +333,14 @@ g_param_value_set_default
 g_param_value_defaults
 g_param_value_validate
 g_param_values_cmp
-g_param_spec_internal
+GParamSpecTypeInfo
+g_param_type_register_static
+GParamSpecPool
 g_param_spec_pool_new
 g_param_spec_pool_insert
 g_param_spec_pool_remove
 g_param_spec_pool_lookup
-g_param_type_register_static
+g_param_spec_internal
 </SECTION>
 
 <SECTION>
@@ -462,18 +469,20 @@ g_signal_type_cclosure_new
 <SECTION>
 <TITLE>Closures</TITLE>
 <FILE>closures</FILE>
-GClosureMarshal
-GClosureNotify
+G_CLOSURE_NEEDS_MARSHAL
+G_CCLOSURE_SWAP_DATA
+G_CALLBACK
+GCallback
 GClosure
 GCClosure
+GClosureMarshal
+GClosureNotify
 GClosureNotifyData
-GCallback
-G_CLOSURE_NEEDS_MARSHAL
-G_CCLOSURE_SWAP_DATA
 g_cclosure_new
 g_cclosure_new_swap
 g_cclosure_new_object
 g_cclosure_new_object_swap
+g_closure_new_object
 g_closure_ref
 g_closure_unref
 g_closure_invoke
index 8a0435d..1fc7fb7 100644 (file)
@@ -14,72 +14,80 @@ Closures
 
 </para>
 
-<!-- ##### USER_FUNCTION GClosureMarshal ##### -->
+<!-- ##### MACRO G_CLOSURE_NEEDS_MARSHAL ##### -->
 <para>
 
 </para>
 
 @closure: 
-@return_value: 
-@n_param_values: 
-@param_values: 
-@invocation_hint: 
-@marshal_data: 
 
 
-<!-- ##### USER_FUNCTION GClosureNotify ##### -->
+<!-- ##### MACRO G_CCLOSURE_SWAP_DATA ##### -->
 <para>
 
 </para>
 
-@data: 
-@closure: 
+@cclosure: 
 
 
-<!-- ##### STRUCT GClosure ##### -->
+<!-- ##### MACRO G_CALLBACK ##### -->
 <para>
 
 </para>
 
-@is_invalid
+@f
 
-<!-- ##### STRUCT GCClosure ##### -->
+
+<!-- ##### TYPEDEF GCallback ##### -->
 <para>
 
 </para>
 
-@closure: 
-@callback: 
 
-<!-- ##### STRUCT GClosureNotifyData ##### -->
+<!-- ##### STRUCT GClosure ##### -->
 <para>
 
 </para>
 
-@data: 
-@notify: 
+@is_invalid: 
 
-<!-- ##### TYPEDEF GCallback ##### -->
+<!-- ##### STRUCT GCClosure ##### -->
 <para>
 
 </para>
 
+@closure: 
+@callback: 
 
-<!-- ##### MACRO G_CLOSURE_NEEDS_MARSHAL ##### -->
+<!-- ##### USER_FUNCTION GClosureMarshal ##### -->
 <para>
 
 </para>
 
 @closure: 
+@return_value: 
+@n_param_values: 
+@param_values: 
+@invocation_hint: 
+@marshal_data: 
 
 
-<!-- ##### MACRO G_CCLOSURE_SWAP_DATA ##### -->
+<!-- ##### USER_FUNCTION GClosureNotify ##### -->
 <para>
 
 </para>
 
-@cclosure: 
+@data: 
+@closure: 
+
+
+<!-- ##### STRUCT GClosureNotifyData ##### -->
+<para>
 
+</para>
+
+@data: 
+@notify: 
 
 <!-- ##### FUNCTION g_cclosure_new ##### -->
 <para>
@@ -123,6 +131,16 @@ Closures
 @Returns: 
 
 
+<!-- ##### FUNCTION g_closure_new_object ##### -->
+<para>
+
+</para>
+
+@sizeof_closure: 
+@object: 
+@Returns: 
+
+
 <!-- ##### FUNCTION g_closure_ref ##### -->
 <para>
 
index 3ba8869..5331962 100644 (file)
@@ -88,6 +88,27 @@ Parameter Specifications
 @type: 
 
 
+<!-- ##### MACRO G_PARAM_READWRITE ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### MACRO G_PARAM_MASK ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### MACRO G_PARAM_USER_SHIFT ##### -->
+<para>
+
+</para>
+
+
+
 <!-- ##### ENUM GParamFlags ##### -->
 <para>
 
@@ -205,19 +226,36 @@ Parameter Specifications
 @Returns: 
 
 
-<!-- ##### FUNCTION g_param_spec_internal ##### -->
+<!-- ##### STRUCT GParamSpecTypeInfo ##### -->
+<para>
+
+</para>
+
+@instance_size: 
+@n_preallocs: 
+@instance_init: 
+@value_type: 
+@finalize: 
+@value_set_default: 
+@value_validate: 
+@values_cmp: 
+
+<!-- ##### FUNCTION g_param_type_register_static ##### -->
 <para>
 
 </para>
 
-@param_type: 
 @name: 
-@nick: 
-@blurb: 
-@flags: 
+@pspec_info: 
 @Returns: 
 
 
+<!-- ##### STRUCT GParamSpecPool ##### -->
+<para>
+
+</para>
+
+
 <!-- ##### FUNCTION g_param_spec_pool_new ##### -->
 <para>
 
@@ -259,13 +297,16 @@ Parameter Specifications
 @Returns: 
 
 
-<!-- ##### FUNCTION g_param_type_register_static ##### -->
+<!-- ##### FUNCTION g_param_spec_internal ##### -->
 <para>
 
 </para>
 
+@param_type: 
 @name: 
-@pspec_info: 
+@nick: 
+@blurb: 
+@flags: 
 @Returns: 
 
 
index 5adeac8..3994dd5 100644 (file)
@@ -2,11 +2,26 @@
 GType
 
 <!-- ##### SECTION Short_Description ##### -->
-
+The GLib Runtime type identification and management system
 
 <!-- ##### SECTION Long_Description ##### -->
 <para>
-
+The GType API is the foundation of the GObject system.  It provides the
+facilities for registering and managing all fundamental data types,
+user-defined object and interface types.  Before using any GType
+or GObject functions, g_type_init() must be called to initialize the
+type system.
+</para>
+<para>
+For type creation and registration purposes, all types fall into one of
+two categories: static or dynamic.  Static types are never loaded or
+unloaded at run-time as dynamic types may be.  Static types are created
+with g_type_register_static() that gets type specific information passed
+in via a #GTypeInfo structure.
+Dynamic types are created with g_type_register_dynamic() which takes a
+#GTypePlugin structure instead. The remaining type information (the
+#GTypeInfo structure) is retrived during runtime through #GTypePlugin
+and the g_type_plugin_*() API.
 </para>
 
 <!-- ##### SECTION See_Also ##### -->
@@ -16,21 +31,25 @@ GType
 
 <!-- ##### TYPEDEF GType ##### -->
 <para>
-
+A numerical value which represents the unique identifier of a registered
+type.
 </para>
 
 
 <!-- ##### MACRO G_TYPE_FUNDAMENTAL ##### -->
 <para>
-
+Returns #TRUE if @type is a fundamental data type such as #G_TYPE_INT or
+#G_TYPE_POINTER. Fundamental types are types that serve as fundaments for
+the derived types, thus they are the roots of distinct inheritance heirachies.
 </para>
 
-@type: 
+@type: a #GType value
 
 
 <!-- ##### MACRO G_TYPE_FUNDAMENTAL_MAX ##### -->
 <para>
-
+An integer constant that represents the number of identifiers reserved
+for types that are assigned at compile-time.
 </para>
 
 
@@ -54,25 +73,32 @@ GType
 
 <!-- ##### MACRO G_TYPE_FUNDAMENTAL_LAST ##### -->
 <para>
-
+An integer that currently represents the highest value of all
+fundamental type identifiers. This is of interest for dynamic
+introduction of new fundamental types (a
+<emphasis>rarely</emphasis> needed feature).
 </para>
 
 
 
 <!-- ##### MACRO G_TYPE_IS_ABSTRACT ##### -->
 <para>
-
+Returns #TRUE if @type is an abstract type.  An abstract type can not be
+instantiated and is normally used as an abstract base class for
+derived classes.
 </para>
 
-@type: 
+@type: A #GType value.
 
 
 <!-- ##### MACRO G_TYPE_IS_DERIVED ##### -->
 <para>
-
+Returns #TRUE if @type is derived (or in object-oriented terminolgy:
+inherited) from another type (this holds true for all non-fundamental
+types).
 </para>
 
-@type: 
+@type: A #GType value.
 
 
 <!-- ##### MACRO G_TYPE_IS_FUNDAMENTAL ##### -->
@@ -80,7 +106,7 @@ GType
 
 </para>
 
-@type: 
+@type: A #GType value.
 
 
 <!-- ##### MACRO G_TYPE_IS_VALUE_TYPE ##### -->
@@ -88,7 +114,7 @@ GType
 
 </para>
 
-@type: 
+@type: A #GType value.
 
 
 <!-- ##### MACRO G_TYPE_IS_CLASSED ##### -->
@@ -96,15 +122,16 @@ GType
 
 </para>
 
-@type: 
+@type: A #GType value.
 
 
 <!-- ##### MACRO G_TYPE_IS_INSTANTIATABLE ##### -->
 <para>
-
+Returns #TRUE if @type can be instantiated.  Instantiation is the
+process of creating an instance (object) of this type.
 </para>
 
-@type: 
+@type: A #GType value.
 
 
 <!-- ##### MACRO G_TYPE_IS_DERIVABLE ##### -->
@@ -112,7 +139,7 @@ GType
 
 </para>
 
-@type: 
+@type: A #GType value.
 
 
 <!-- ##### MACRO G_TYPE_IS_DEEP_DERIVABLE ##### -->
@@ -120,15 +147,18 @@ GType
 
 </para>
 
-@type: 
+@type: A #GType value.
 
 
 <!-- ##### MACRO G_TYPE_IS_INTERFACE ##### -->
 <para>
-
+Returns #TRUE if @type is an interface type.
+Interface types are types that provide pure APIs, the implementation
+of which is provided by another type (which is then said to conform
+to the interface).
 </para>
 
-@type: 
+@type: A #GType value.
 
 
 <!-- ##### ENUM GTypeFundamentals ##### -->
@@ -195,19 +225,27 @@ GType
 
 <!-- ##### STRUCT GTypeInfo ##### -->
 <para>
-
-</para>
-
-@class_size: 
-@base_init: 
-@base_finalize: 
-@class_init: 
-@class_finalize: 
-@class_data: 
-@instance_size: 
-@n_preallocs: 
-@instance_init: 
-@value_table: 
+This structure is used to provide the type system with the information
+required to initialize and destruct (finalize) a type's class and
+instances thereof.
+The initialized structure is passed to the g_type_register_static() function
+(or is copied into the provided #GTypeInfo structure in the
+g_type_plugin_complete_type_info()). The type system will perform a deep
+copy of this structure, so it's memory does not need to be persistent
+across invocation of g_type_register_static().
+</para>
+
+@class_size:    Size of the class structure (required for interface, classed and instantiatable types).
+@base_init:     Location of the base initialization function (optional).
+@base_finalize:         Location of the base finalization function (optional).
+@class_init:    Location of the class initialization function (optional, for classed and instantiatable types only).
+@class_finalize: Location of the class finalization function (optional).
+@class_data:    User-supplied data passed to the class init/finalize functions.
+@instance_size:         Size of the instance (object) structure (required for instantiatable types only).
+@n_preallocs:   Number of pre-allocated (cached) instances to reserve memory for (0 indicates no caching).
+@instance_init:         The location of the instance initialization function (optional, for instantiatable types only).
+@value_table:   Function table for generic handling of GValues of this type (usualy only usefull for
+                fundamental types).
 
 <!-- ##### STRUCT GTypeFundamentalInfo ##### -->
 <para>
@@ -346,6 +384,13 @@ GType
 @g_type: 
 
 
+<!-- ##### MACRO G_TYPE_FLAG_RESERVED_ID_BIT ##### -->
+<para>
+
+</para>
+
+
+
 <!-- ##### FUNCTION g_type_init ##### -->
 <para>
 Prior to any use of the type system, g_type_init() has to be called to initialize
index b7907b3..9e568b2 100644 (file)
@@ -371,6 +371,15 @@ Standard value types
 @v_pointer: 
 
 
+<!-- ##### FUNCTION g_value_get_as_pointer ##### -->
+<para>
+
+</para>
+
+@value: 
+@Returns: 
+
+
 <!-- ##### FUNCTION g_value_set_ccallback ##### -->
 <para>
 
index 8a1d14c..979ba2c 100644 (file)
@@ -1,3 +1,16 @@
+Wed Jan 31 06:19:49 2001  Tim Janik  <timj@gtk.org>
+
+       * gparam.h: gtk-doc sucks for not dealing with #define inside enums.
+
+       * gtype.[hc]: added G_TYPE_FLAG_RESERVED_ID_BIT, a bit in the type
+       number that's supposed to be left untouched (preserved mainly
+       for the signal code).
+
+       * *.c: added thread safety code, based on an old patch from sebastian.
+       the remaining thread safety issues are now datalists on pspecs (to be
+       solved im gdataset.c) and gvalue.c where locking concerns value exchange
+       functionality only, and that's soon to be revised.
+
 2001-01-27  Tor Lillqvist  <tml@iki.fi>
 
        * makefile.msc.in: Don't try to compile gmarshal.c on its own.
index d99b718..d303f2b 100644 (file)
@@ -16,6 +16,7 @@
  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  * Boston, MA 02111-1307, USA.
  */
+
 #include       "gclosure.h"
 
 #include       "gvalue.h"
index e60ec20..4ef62d0 100644 (file)
  * Boston, MA 02111-1307, USA.
  */
 
+/*
+ * MT safe
+ */
+
 #include        <string.h>
 
 #include       "genums.h"
index f4b8233..916996d 100644 (file)
  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  * Boston, MA 02111-1307, USA.
  */
+
+/*
+ * MT safe
+ */
+
 #include       "gobject.h"
 
 
@@ -140,9 +145,10 @@ static gulong               gobject_signals[LAST_SIGNAL] = { 0, };
 gboolean glib_debug_objects = FALSE;
 
 #ifdef G_ENABLE_DEBUG
+G_LOCK_DEFINE_STATIC     (debug_objects);
 static volatile GObject *glib_trap_object_ref = NULL;
-static guint             debug_objects_count = 0;
-static GHashTable       *debug_objects_ht = NULL;
+static guint            debug_objects_count = 0;
+static GHashTable      *debug_objects_ht = NULL;
 static void
 debug_objects_foreach (gpointer key,
                       gpointer value,
@@ -158,6 +164,7 @@ debug_objects_foreach (gpointer key,
 static void
 debug_objects_atexit (void)
 {
+  G_LOCK (debug_objects);
   if (glib_debug_objects)
     {
       if (debug_objects_ht)
@@ -166,6 +173,7 @@ debug_objects_atexit (void)
          g_hash_table_foreach (debug_objects_ht, debug_objects_foreach, NULL);
        }
     }
+  G_UNLOCK (debug_objects);
 }
 #endif /* G_ENABLE_DEBUG */
 
@@ -433,6 +441,7 @@ g_object_init (GObject *object)
   object_freeze_notifies (object);
 
 #ifdef G_ENABLE_DEBUG
+  G_LOCK (debug_objects);
   if (glib_debug_objects)
     {
       if (!debug_objects_ht)
@@ -440,6 +449,7 @@ g_object_init (GObject *object)
       debug_objects_count++;
       g_hash_table_insert (debug_objects_ht, object, object);
     }
+  G_UNLOCK (debug_objects);
 #endif /* G_ENABLE_DEBUG */
 }
 
@@ -522,8 +532,10 @@ g_object_last_unref (GObject *object)
     {
       G_OBJECT_GET_CLASS (object)->finalize (object);
 #ifdef G_ENABLE_DEBUG
+      G_LOCK (debug_objects);
       if (glib_debug_objects && debug_objects_ht)
        g_assert (g_hash_table_lookup (debug_objects_ht, object) == NULL);
+      G_UNLOCK (debug_objects);
 #endif /* G_ENABLE_DEBUG */
       g_type_free_instance ((GTypeInstance*) object);
     }
@@ -545,6 +557,7 @@ g_object_finalize (GObject *object)
   g_datalist_clear (&object->qdata);
   
 #ifdef G_ENABLE_DEBUG
+  G_LOCK (debug_objects);
   if (glib_debug_objects)
     {
       g_assert (g_hash_table_lookup (debug_objects_ht, object) == object);
@@ -552,6 +565,7 @@ g_object_finalize (GObject *object)
       g_hash_table_remove (debug_objects_ht, object);
       debug_objects_count--;
     }
+  G_UNLOCK (debug_objects);
 #endif /* G_ENABLE_DEBUG */
 }
 
index 3e6b52c..0c99722 100644 (file)
  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  * Boston, MA 02111-1307, USA.
  */
+
+/*
+ * MT safe
+ */
+
 #include       "gparam.h"
 
 
 
 
 /* --- defines --- */
-#define G_PARAM_SPEC_CLASS(class)    (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_PARAM, GParamSpecClass))
-#define PSPEC_APPLIES_TO_VALUE(pspec, value)  (G_TYPE_CHECK_VALUE_TYPE ((value), G_PARAM_SPEC_VALUE_TYPE (pspec)))
+#define G_PARAM_SPEC_CLASS(class)              (G_TYPE_CHECK_CLASS_CAST ((class), G_TYPE_PARAM, GParamSpecClass))
+#define        G_PARAM_USER_MASK                       ((1 << G_PARAM_USER_SHIFT) - 1)
+#define PSPEC_APPLIES_TO_VALUE(pspec, value)   (G_TYPE_CHECK_VALUE_TYPE ((value), G_PARAM_SPEC_VALUE_TYPE (pspec)))
+#define        G_SLOCK(mutex)                          g_static_mutex_lock (mutex)
+#define        G_SUNLOCK(mutex)                        g_static_mutex_unlock (mutex)
 
 
 /* --- prototypes --- */
@@ -54,6 +62,7 @@ static gchar* value_param_lcopy_value         (const GValue   *value,
 
 /* --- variables --- */
 static GQuark quark_floating = 0;
+G_LOCK_DEFINE_STATIC (pspec_ref_count);
 
 
 /* --- functions --- */
@@ -151,10 +160,19 @@ GParamSpec*
 g_param_spec_ref (GParamSpec *pspec)
 {
   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
-  g_return_val_if_fail (pspec->ref_count > 0, NULL);
-
-  pspec->ref_count += 1;
 
+  G_LOCK (pspec_ref_count);
+  if (pspec->ref_count > 0)
+    {
+      pspec->ref_count += 1;
+      G_UNLOCK (pspec_ref_count);
+    }
+  else
+    {
+      G_UNLOCK (pspec_ref_count);
+      g_return_val_if_fail (pspec->ref_count > 0, NULL);
+    }
+  
   return pspec;
 }
 
@@ -162,27 +180,53 @@ void
 g_param_spec_unref (GParamSpec *pspec)
 {
   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
-  g_return_if_fail (pspec->ref_count > 0);
 
-  /* sync with _sink */
-  pspec->ref_count -= 1;
-  if (pspec->ref_count == 0)
-    G_PARAM_SPEC_GET_CLASS (pspec)->finalize (pspec);
+  G_LOCK (pspec_ref_count);
+  if (pspec->ref_count > 0)
+    {
+      gboolean need_finalize;
+
+      /* sync with _sink */
+      pspec->ref_count -= 1;
+      need_finalize = pspec->ref_count == 0;
+      G_UNLOCK (pspec_ref_count);
+      if (need_finalize)
+       G_PARAM_SPEC_GET_CLASS (pspec)->finalize (pspec);
+    }
+  else
+    {
+      G_UNLOCK (pspec_ref_count);
+      g_return_if_fail (pspec->ref_count > 0);
+    }
 }
 
 void
 g_param_spec_sink (GParamSpec *pspec)
 {
   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
-  g_return_if_fail (pspec->ref_count > 0);
 
-  if (g_datalist_id_remove_no_notify (&pspec->qdata, quark_floating))
+  G_LOCK (pspec_ref_count);
+  if (pspec->ref_count > 0)
     {
-      /* sync with _unref */
-      if (pspec->ref_count > 1)
-       pspec->ref_count -= 1;
-      else
-       g_param_spec_unref (pspec);
+      if (g_datalist_id_remove_no_notify (&pspec->qdata, quark_floating))
+       {
+         /* sync with _unref */
+         if (pspec->ref_count > 1)
+           pspec->ref_count -= 1;
+         else
+           {
+             G_UNLOCK (pspec_ref_count);
+             g_param_spec_unref (pspec);
+
+             return;
+           }
+       }
+      G_UNLOCK (pspec_ref_count);
+    }
+  else
+    {
+      G_UNLOCK (pspec_ref_count);
+      g_return_if_fail (pspec->ref_count > 0);
     }
 }
 
@@ -405,8 +449,9 @@ value_param_lcopy_value (const GValue *value,
 /* --- param spec pool --- */
 struct _GParamSpecPool
 {
-  gboolean    type_prefixing;
-  GHashTable *hash_table;
+  GStaticMutex smutex;
+  gboolean     type_prefixing;
+  GHashTable  *hash_table;
 };
 
 static guint
@@ -436,8 +481,10 @@ param_spec_pool_equals (gconstpointer key_spec_1,
 GParamSpecPool*
 g_param_spec_pool_new (gboolean type_prefixing)
 {
+  static GStaticMutex init_smutex = G_STATIC_MUTEX_INIT;
   GParamSpecPool *pool = g_new (GParamSpecPool, 1);
 
+  memcpy (&pool->smutex, &init_smutex, sizeof (init_smutex));
   pool->type_prefixing = type_prefixing != FALSE;
   pool->hash_table = g_hash_table_new (param_spec_pool_hash, param_spec_pool_equals);
 
@@ -450,37 +497,52 @@ g_param_spec_pool_insert (GParamSpecPool *pool,
                          GType           owner_type)
 {
   gchar *p;
-
-  g_return_if_fail (pool != NULL);
-  g_return_if_fail (pspec);
-  g_return_if_fail (owner_type > 0);
-  g_return_if_fail (pspec->owner_type == 0);
-
-  for (p = pspec->name; *p; p++)
+  
+  if (pool && pspec && owner_type > 0 && pspec->owner_type == 0)
     {
-      if (!strchr (G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-_", *p))
+      G_SLOCK (&pool->smutex);
+      for (p = pspec->name; *p; p++)
        {
-         g_warning (G_STRLOC ": pspec name \"%s\" contains invalid characters", pspec->name);
-         return;
+         if (!strchr (G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-_", *p))
+           {
+             g_warning (G_STRLOC ": pspec name \"%s\" contains invalid characters", pspec->name);
+             G_SUNLOCK (&pool->smutex);
+             return;
+           }
        }
+      
+      pspec->owner_type = owner_type;
+      g_param_spec_ref (pspec);
+      g_hash_table_insert (pool->hash_table, pspec, pspec);
+      G_SUNLOCK (&pool->smutex);
+    }
+  else
+    {
+      g_return_if_fail (pool != NULL);
+      g_return_if_fail (pspec);
+      g_return_if_fail (owner_type > 0);
+      g_return_if_fail (pspec->owner_type == 0);
     }
-
-  pspec->owner_type = owner_type;
-  g_param_spec_ref (pspec);
-  g_hash_table_insert (pool->hash_table, pspec, pspec);
 }
 
 void
 g_param_spec_pool_remove (GParamSpecPool *pool,
                          GParamSpec     *pspec)
 {
-  g_return_if_fail (pool != NULL);
-  g_return_if_fail (pspec);
-
-  if (g_hash_table_remove (pool->hash_table, pspec))
-    g_param_spec_unref (pspec);
+  if (pool && pspec)
+    {
+      G_SLOCK (&pool->smutex);
+      if (g_hash_table_remove (pool->hash_table, pspec))
+       g_param_spec_unref (pspec);
+      else
+       g_warning (G_STRLOC ": attempt to remove unknown pspec `%s' from pool", pspec->name);
+      G_SUNLOCK (&pool->smutex);
+    }
   else
-    g_warning (G_STRLOC ": attempt to remove unknown pspec `%s' from pool", pspec->name);
+    {
+      g_return_if_fail (pool != NULL);
+      g_return_if_fail (pspec);
+    }
 }
 
 static inline GParamSpec*
@@ -542,8 +604,13 @@ g_param_spec_pool_lookup (GParamSpecPool *pool,
   GParamSpec *pspec;
   gchar *delim;
 
-  g_return_val_if_fail (pool != NULL, NULL);
-  g_return_val_if_fail (param_name, NULL);
+  if (!pool || !param_name)
+    {
+      g_return_val_if_fail (pool != NULL, NULL);
+      g_return_val_if_fail (param_name != NULL, NULL);
+    }
+
+  G_SLOCK (&pool->smutex);
 
   delim = strchr (param_name, ':');
 
@@ -552,7 +619,10 @@ g_param_spec_pool_lookup (GParamSpecPool *pool,
     {
       if (trailer_p)
        *trailer_p = NULL;
-      return param_spec_ht_lookup (pool->hash_table, param_name, owner_type, walk_ancestors);
+      pspec = param_spec_ht_lookup (pool->hash_table, param_name, owner_type, walk_ancestors);
+      G_SUNLOCK (&pool->smutex);
+
+      return pspec;
     }
 
   /* strip type prefix */
@@ -574,6 +644,8 @@ g_param_spec_pool_lookup (GParamSpecPool *pool,
            {
              if (trailer_p)
                *trailer_p = NULL;
+             G_SUNLOCK (&pool->smutex);
+
              return NULL;
            }
          owner_type = type;
@@ -583,7 +655,10 @@ g_param_spec_pool_lookup (GParamSpecPool *pool,
            {
              if (trailer_p)
                *trailer_p = NULL;
-             return param_spec_ht_lookup (pool->hash_table, param_name, owner_type, walk_ancestors);
+             pspec = param_spec_ht_lookup (pool->hash_table, param_name, owner_type, walk_ancestors);
+              G_SUNLOCK (&pool->smutex);
+
+             return pspec;
            }
        }
     }
@@ -601,12 +676,16 @@ g_param_spec_pool_lookup (GParamSpecPool *pool,
        g_free (buffer);
       if (trailer_p)
        *trailer_p = pspec ? delim + 2 : NULL;
+      G_SUNLOCK (&pool->smutex);
+
       return pspec;
     }
 
   /* malformed param_name */
   if (trailer_p)
     *trailer_p = NULL;
+  G_SUNLOCK (&pool->smutex);
+
   return NULL;
 }
 
index bf8a16c..3a27b1f 100644 (file)
@@ -48,12 +48,12 @@ typedef enum
   G_PARAM_WRITABLE            = 1 << 1,
   G_PARAM_CONSTRUCT          = 1 << 2,
   G_PARAM_CONSTRUCT_ONLY      = 1 << 3,
-  G_PARAM_PRIVATE            = 1 << 4,
-#define        G_PARAM_MASK            (0x000000ff)
-  /* bits in the range 0xffffff00 are reserved for 3rd party usage */
-#define        G_PARAM_USER_MASK       (0xffffff00)
+  G_PARAM_PRIVATE            = 1 << 4
 } GParamFlags;
 #define        G_PARAM_READWRITE       (G_PARAM_READABLE | G_PARAM_WRITABLE)
+#define        G_PARAM_MASK            (0x000000ff)
+/* bits in the range 0xffffff00 are reserved for 3rd party usage */
+#define        G_PARAM_USER_SHIFT      (8)
 
 
 /* --- typedefs & structures --- */
index e42a832..cc40f73 100644 (file)
  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  * Boston, MA 02111-1307, USA.
  */
+
+/*
+ * MT safe
+ */
+
 #include       "gparamspecs.h"
 
 #include       "gvaluecollector.h"
index 16f464b..c251670 100644 (file)
  * this code is based on the original GtkSignal implementation
  * for the Gtk+ library by Peter Mattis <petm@xcf.berkeley.edu>
  */
-#include <string.h> 
+
+/*
+ * MT safe
+ */
 
 #include        "gsignal.h"
 #include        "gbsearcharray.h"
 #include        "gvaluecollector.h"
+#include       <string.h> 
 
 
 /* pre allocation configurations
@@ -64,26 +68,10 @@ g_generic_node_alloc (GTrashStack **trash_stack_p,
   
   return node;
 }
-static inline void
-g_generic_node_free (GTrashStack **trash_stack_p,
-                     gpointer      node)
-{
-  g_trash_stack_push (trash_stack_p, node);
-}
+#define        g_generic_node_free(trash_stack_p, node) g_trash_stack_push (trash_stack_p, node)
 #else  /* !DISABLE_MEM_POOLS */
-static inline gpointer
-g_generic_node_alloc (GTrashStack **trash_stack_p,
-                      guint         sizeof_node,
-                      guint         nodes_pre_alloc)
-{
-  return g_malloc (sizeof_node);
-}
-static inline void
-g_generic_node_free (GTrashStack **trash_stack_p,
-                     gpointer      node)
-{
-  g_free (node);
-}
+#define        g_generic_node_alloc(t,sizeof_node,p)    g_malloc (sizeof_node)
+#define        g_generic_node_free(t,node)              g_free (node)
 #endif /* !DISABLE_MEM_POOLS */
 
 
@@ -2027,6 +2015,6 @@ signal_emit_R (SignalNode   *node,
 }
 
 
-/* compile standard marshallers */
+/* --- compile standard marshallers --- */
 #include       "gvaluetypes.h"
 #include        "gmarshal.c"
index 6aba911..6aaa94b 100644 (file)
  *
  * FIXME:
  * - force interface initialization for already existing classes
- * - make things threadsafe
+ *
+ * LOCKING:
+ * lock handling issues when calling static functions are indicated by
+ * uppercase letter postfixes, all static functions have to have
+ * one of the below postfixes:
+ * - _I:       [Indifferent about locking]
+ *   function doesn't care about locks at all
+ * - _U:       [Unlocked invocation]
+ *   no read or write lock has to be held across function invocation
+ *   (locks may be acquired and released during invocation though)
+ * - _L:       [Locked invocation]
+ *   a write lock or more than 0 read locks have to be held across
+ *   function invocation
+ * - _W:       [Write-locked invocation]
+ *   a write lock has to be held across function invokation
+ * - _Wm:      [Write-locked invocation, mutatable]
+ *   like _W, but the write lock might be released and reacquired
+ *   during invocation, watch your pointers
  */
 
+static GStaticRWLock            type_rw_lock = G_STATIC_RW_LOCK_INIT;
+#define G_READ_LOCK(rw_lock)    g_static_rw_lock_reader_lock (rw_lock)
+#define G_READ_UNLOCK(rw_lock)  g_static_rw_lock_reader_unlock (rw_lock)
+#define G_WRITE_LOCK(rw_lock)   g_static_rw_lock_writer_lock (rw_lock)
+#define G_WRITE_UNLOCK(rw_lock) g_static_rw_lock_writer_unlock (rw_lock)
+#define        INVALID_RECURSION(func, arg, type_name) G_STMT_START{ \
+    static const gchar *_action = " invalidly modified type "; \
+    gpointer _arg = (gpointer) (arg); gchar *_tname = (type_name), *_fname = (func); \
+    if (_arg) \
+      g_error ("%s(%p)%s`%s'", _fname, _arg, _action, _tname); \
+    else \
+      g_error ("%s()%s`%s'", _fname, _action, _tname); \
+}G_STMT_END
+
 #define TYPE_FUNDAMENTAL_FLAG_MASK (G_TYPE_FLAG_CLASSED | \
                                    G_TYPE_FLAG_INSTANTIATABLE | \
                                    G_TYPE_FLAG_DERIVABLE | \
@@ -46,7 +77,6 @@
 #define        TYPE_FLAG_MASK             (G_TYPE_FLAG_ABSTRACT)
 
 
-
 /* --- typedefs --- */
 typedef struct _TypeNode        TypeNode;
 typedef struct _CommonData      CommonData;
@@ -59,17 +89,17 @@ typedef struct _IFaceHolder IFaceHolder;
 
 
 /* --- prototypes --- */
-static inline GTypeFundamentalInfo*    type_node_fundamental_info      (TypeNode               *node);
-static       void                      type_add_flags                  (TypeNode               *node,
+static inline GTypeFundamentalInfo*    type_node_fundamental_info_L    (TypeNode               *node);
+static       void                      type_add_flags_W                (TypeNode               *node,
                                                                         GTypeFlags              flags);
-static       void                      type_data_make                  (TypeNode               *node,
+static       void                      type_data_make_W                (TypeNode               *node,
                                                                         const GTypeInfo        *info,
                                                                         const GTypeValueTable  *value_table);
-static inline void                     type_data_ref                   (TypeNode               *node);
-static inline void                     type_data_unref                 (TypeNode               *node,
-                                                                        gboolean                uncached);
-static       void                      type_data_last_unref            (GType                   type,
-                                                                        gboolean                uncached);
+static inline void                     type_data_ref_Wm                (TypeNode               *node);
+static inline void                     type_data_unref_Wm              (TypeNode               *node,
+                                                                        gboolean                uncached);
+static       void                      type_data_last_unref_Wm         (GType                   type,
+                                                                        gboolean                uncached);
 
 
 /* --- structures --- */
@@ -89,7 +119,7 @@ struct _TypeNode
   GType       *children;
   TypeData    *data;
   GQuark       qname;
-  GData       *static_gdata;
+  GData       *global_gdata;
   union {
     IFaceEntry  *iface_entries;
     IFaceHolder *iface_conformants;
@@ -97,9 +127,12 @@ struct _TypeNode
   GType        supers[1]; /* flexible array */
 };
 #define SIZEOF_BASE_TYPE_NODE()        (G_STRUCT_OFFSET (TypeNode, supers))
-#define MAX_N_SUPERS    (255)
-#define MAX_N_CHILDREN  (4095)
-#define MAX_N_IFACES    (511)
+#define MAX_N_SUPERS           (255)
+#define MAX_N_CHILDREN         (4095)
+#define MAX_N_IFACES           (511)
+#define NODE_TYPE(node)         (node->supers[0])
+#define NODE_PARENT_TYPE(node)  (node->supers[1])
+#define NODE_NAME(node)         (g_quark_to_string (node->qname))
 
 struct _IFaceHolder
 {
@@ -165,10 +198,10 @@ typedef struct {
 
 
 /* --- variables --- */
-static guint           n_class_cache_funcs = 0;
-static ClassCacheFunc *class_cache_funcs = NULL;
-static GType           last_fundamental_id = 0;
-static GQuark          quark_type_flags = 0;
+static guint           static_n_class_cache_funcs = 0;
+static ClassCacheFunc *static_class_cache_funcs = NULL;
+static GType           static_last_fundamental_id = 0;
+static GQuark          static_quark_type_flags = 0;
 
 
 /* --- externs --- */
@@ -176,42 +209,41 @@ const char  *g_log_domain_gruntime = "GRuntime";
 
 
 /* --- type nodes --- */
-static GHashTable       *g_type_nodes_ht = NULL;
-static GType            *g_branch_seqnos = NULL;
-static TypeNode       ***g_type_nodes = NULL;
+static GHashTable       *static_type_nodes_ht = NULL;
+static GType            *static_branch_seqnos = NULL;
+static TypeNode       ***static_type_nodes = NULL;
 
 static inline TypeNode*
-LOOKUP_TYPE_NODE (register GType utype)
+lookup_type_node_L (register GType utype)
 {
   register GType ftype = G_TYPE_FUNDAMENTAL (utype);
   register GType b_seqno = G_TYPE_BRANCH_SEQNO (utype);
-
-  if (ftype < last_fundamental_id && b_seqno < g_branch_seqnos[ftype])
-    return g_type_nodes[ftype][b_seqno];
+  
+  if (ftype < static_last_fundamental_id && b_seqno < static_branch_seqnos[ftype])
+    return static_type_nodes[ftype][b_seqno];
   else
     return NULL;
 }
-#define NODE_TYPE(node)         (node->supers[0])
-#define NODE_PARENT_TYPE(node)  (node->supers[1])
-#define NODE_NAME(node)         (g_quark_to_string (node->qname))
 
 static TypeNode*
-type_node_any_new (TypeNode              *pnode,
-                  GType                  ftype,
-                  const gchar           *name,
-                  GTypePlugin           *plugin,
-                  GTypeFundamentalFlags  type_flags)
+type_node_any_new_W (TypeNode             *pnode,
+                    GType                 ftype,
+                    const gchar          *name,
+                    GTypePlugin          *plugin,
+                    GTypeFundamentalFlags type_flags)
 {
-  guint branch_last, n_supers = pnode ? pnode->n_supers + 1 : 0;
+  guint branch_last, n_supers;
   GType type;
   TypeNode *node;
   guint i, node_size = 0;
-
-  branch_last = g_branch_seqnos[ftype]++;
+  
+  n_supers = pnode ? pnode->n_supers + 1 : 0;
+  branch_last = static_branch_seqnos[ftype]++;
   type = G_TYPE_DERIVE_ID (ftype, branch_last);
-  if (!branch_last || g_bit_storage (branch_last - 1) < g_bit_storage (g_branch_seqnos[ftype] - 1))
-    g_type_nodes[ftype] = g_renew (TypeNode*, g_type_nodes[ftype], 1 << g_bit_storage (g_branch_seqnos[ftype] - 1));
-
+  g_assert ((type & G_TYPE_FLAG_RESERVED_ID_BIT) == 0);
+  if (!branch_last || g_bit_storage (branch_last - 1) < g_bit_storage (static_branch_seqnos[ftype] - 1))
+    static_type_nodes[ftype] = g_renew (TypeNode*, static_type_nodes[ftype], 1 << g_bit_storage (static_branch_seqnos[ftype] - 1));
+  
   if (!pnode)
     node_size += sizeof (GTypeFundamentalInfo);              /* fundamental type info */
   node_size += SIZEOF_BASE_TYPE_NODE ();             /* TypeNode structure */
@@ -219,18 +251,18 @@ type_node_any_new (TypeNode              *pnode,
   node = g_malloc0 (node_size);
   if (!pnode)                                        /* offset fundamental types */
     node = G_STRUCT_MEMBER_P (node, sizeof (GTypeFundamentalInfo));
-  g_type_nodes[ftype][branch_last] = node;
-
+  static_type_nodes[ftype][branch_last] = node;
+  
   node->n_supers = n_supers;
   if (!pnode)
     {
       node->supers[0] = type;
       node->supers[1] = 0;
-
+      
       node->is_classed = (type_flags & G_TYPE_FLAG_CLASSED) != 0;
       node->is_instantiatable = (type_flags & G_TYPE_FLAG_INSTANTIATABLE) != 0;
       node->is_iface = G_TYPE_IS_INTERFACE (type);
-
+      
       node->n_ifaces = 0;
       if (node->is_iface)
        node->private.iface_conformants = NULL;
@@ -241,11 +273,11 @@ type_node_any_new (TypeNode              *pnode,
     {
       node->supers[0] = type;
       memcpy (node->supers + 1, pnode->supers, sizeof (GType) * (1 + pnode->n_supers + 1));
-
+      
       node->is_classed = pnode->is_classed;
       node->is_instantiatable = pnode->is_instantiatable;
       node->is_iface = pnode->is_iface;
-
+      
       if (node->is_iface)
        {
          node->n_ifaces = 0;
@@ -262,93 +294,95 @@ type_node_any_new (TypeNode              *pnode,
       pnode->children = g_renew (GType, pnode->children, pnode->n_children);
       pnode->children[i] = type;
     }
-
+  
   node->plugin = plugin;
   node->n_children = 0;
   node->children = NULL;
   node->data = NULL;
   node->qname = g_quark_from_string (name);
-  node->static_gdata = NULL;
-
-  g_hash_table_insert (g_type_nodes_ht,
+  node->global_gdata = NULL;
+  
+  g_hash_table_insert (static_type_nodes_ht,
                       GUINT_TO_POINTER (node->qname),
                       GUINT_TO_POINTER (type));
-
   return node;
 }
 
 static inline GTypeFundamentalInfo*
-type_node_fundamental_info (TypeNode *node)
+type_node_fundamental_info_L (TypeNode *node)
 {
   GType ftype = G_TYPE_FUNDAMENTAL (NODE_TYPE (node));
   
   if (ftype != NODE_TYPE (node))
-    node = LOOKUP_TYPE_NODE (ftype);
+    node = lookup_type_node_L (ftype);
   
   return node ? G_STRUCT_MEMBER_P (node, - (gssize) sizeof (GTypeFundamentalInfo)) : NULL;
 }
 
 static TypeNode*
-type_node_fundamental_new (GType                 ftype,
-                          const gchar          *name,
-                          GTypeFundamentalFlags type_flags)
+type_node_fundamental_new_W (GType                 ftype,
+                            const gchar          *name,
+                            GTypeFundamentalFlags type_flags)
 {
   GTypeFundamentalInfo *finfo;
   TypeNode *node;
-  guint i, flast = last_fundamental_id;
+  guint i, flast;
+  
+  flast = static_last_fundamental_id;
   
   g_assert (ftype == G_TYPE_FUNDAMENTAL (ftype));
   
   type_flags &= TYPE_FUNDAMENTAL_FLAG_MASK;
-
-  last_fundamental_id = MAX (last_fundamental_id, ftype + 1);
-  if (last_fundamental_id > flast)
+  
+  static_last_fundamental_id = MAX (static_last_fundamental_id, ftype + 1);
+  if (static_last_fundamental_id > flast)
     {
-      g_type_nodes = g_renew (TypeNode**, g_type_nodes, last_fundamental_id);
-      g_branch_seqnos = g_renew (GType, g_branch_seqnos, last_fundamental_id);
-      for (i = flast; i < last_fundamental_id; i++)
+      static_type_nodes = g_renew (TypeNode**, static_type_nodes, static_last_fundamental_id);
+      static_branch_seqnos = g_renew (GType, static_branch_seqnos, static_last_fundamental_id);
+      for (i = flast; i < static_last_fundamental_id; i++)
        {
-         g_type_nodes[i] = NULL;
-         g_branch_seqnos[i] = 0;
+         static_type_nodes[i] = NULL;
+         static_branch_seqnos[i] = 0;
        }
     }
-  g_assert (g_branch_seqnos[ftype] == 0);
-
-  node = type_node_any_new (NULL, ftype, name, NULL, type_flags);
-  finfo = type_node_fundamental_info (node);
+  g_assert (static_branch_seqnos[ftype] == 0);
+  
+  node = type_node_any_new_W (NULL, ftype, name, NULL, type_flags);
+  
+  finfo = type_node_fundamental_info_L (node);
   finfo->type_flags = type_flags;
-
+  
   return node;
 }
 
 static TypeNode*
-type_node_new (TypeNode    *pnode,
-              const gchar *name,
-              GTypePlugin *plugin)
-
+type_node_new_W (TypeNode    *pnode,
+                const gchar *name,
+                GTypePlugin *plugin)
+     
 {
   g_assert (pnode);
   g_assert (pnode->n_supers < MAX_N_SUPERS);
   g_assert (pnode->n_children < MAX_N_CHILDREN);
-
-  return type_node_any_new (pnode, G_TYPE_FUNDAMENTAL (NODE_TYPE (pnode)), name, plugin, 0);
+  
+  return type_node_any_new_W (pnode, G_TYPE_FUNDAMENTAL (NODE_TYPE (pnode)), name, plugin, 0);
 }
 
 static inline IFaceEntry*
-type_lookup_iface_entry (TypeNode *node,
-                        TypeNode *iface)
+type_lookup_iface_entry_L (TypeNode *node,
+                          TypeNode *iface)
 {
   if (iface->is_iface && node->n_ifaces)
     {
       IFaceEntry *ifaces = node->private.iface_entries - 1;
       guint n_ifaces = node->n_ifaces;
       GType iface_type = NODE_TYPE (iface);
-
+      
       do
        {
          guint i;
          IFaceEntry *check;
-
+         
          i = (n_ifaces + 1) / 2;
          check = ifaces + i;
          if (iface_type == check->iface_type)
@@ -363,31 +397,45 @@ type_lookup_iface_entry (TypeNode *node,
        }
       while (n_ifaces);
     }
-
+  
   return NULL;
 }
 
 static inline gchar*
-type_descriptive_name (GType type)
+type_descriptive_name_L (GType type)
 {
   if (type)
     {
-      gchar *name = g_type_name (type);
-
-      return name ? name : "<unknown>";
+      TypeNode *node = lookup_type_node_L (type);
+      
+      return node ? NODE_NAME (node) : "<unknown>";
     }
   else
     return "<invalid>";
 }
 
+static inline gchar*
+type_descriptive_name_U (GType type)
+{
+  gchar *name;
+  
+  G_READ_LOCK (&type_rw_lock);
+  name = type_descriptive_name_L (type);
+  G_READ_UNLOCK (&type_rw_lock);
+  
+  return name;
+}
+
 
 /* --- type consistency checks --- */
 static gboolean
-check_plugin (GTypePlugin *plugin,
-             gboolean     need_complete_type_info,
-             gboolean     need_complete_interface_info,
-             const gchar *type_name)
+check_plugin_U (GTypePlugin *plugin,
+               gboolean     need_complete_type_info,
+               gboolean     need_complete_interface_info,
+               const gchar *type_name)
 {
+  /* G_IS_TYPE_PLUGIN() and G_TYPE_PLUGIN_GET_CLASS() are external calls: _U 
+   */
   if (!plugin)
     {
       g_warning ("plugin handle for type `%s' is NULL",
@@ -416,12 +464,12 @@ check_plugin (GTypePlugin *plugin,
 }
 
 static gboolean
-check_type_name (const gchar *type_name)
+check_type_name_U (const gchar *type_name)
 {
   static const gchar *extra_chars = "-_+";
   const gchar *p = type_name;
   gboolean name_valid;
-
+  
   if (!type_name[0] || !type_name[1] || !type_name[2])
     {
       g_warning ("type name `%s' is too short", type_name);
@@ -444,27 +492,32 @@ check_type_name (const gchar *type_name)
       g_warning ("cannot register existing type `%s'", type_name);
       return FALSE;
     }
-
+  
   return TRUE;
 }
 
 static gboolean
-check_derivation (GType        parent_type,
-                 const gchar *type_name)
+check_derivation_U (GType        parent_type,
+                   const gchar *type_name)
 {
-  TypeNode *pnode = LOOKUP_TYPE_NODE (parent_type);
-  GTypeFundamentalInfo* finfo = type_node_fundamental_info (pnode);
+  TypeNode *pnode;
+  GTypeFundamentalInfo* finfo;
   
+  G_READ_LOCK (&type_rw_lock);
+  pnode = lookup_type_node_L (parent_type);
   if (!pnode)
     {
+      G_READ_UNLOCK (&type_rw_lock);
       g_warning ("cannot derive type `%s' from invalid parent type `%s'",
                 type_name,
-                type_descriptive_name (parent_type));
+                type_descriptive_name_U (parent_type));
       return FALSE;
     }
+  finfo = type_node_fundamental_info_L (pnode);
   /* ensure flat derivability */
   if (!(finfo->type_flags & G_TYPE_FLAG_DERIVABLE))
     {
+      G_READ_UNLOCK (&type_rw_lock);
       g_warning ("cannot derive `%s' from non-derivable parent type `%s'",
                 type_name,
                 NODE_NAME (pnode));
@@ -474,18 +527,20 @@ check_derivation (GType        parent_type,
   if (parent_type != G_TYPE_FUNDAMENTAL (parent_type) &&
       !(finfo->type_flags & G_TYPE_FLAG_DEEP_DERIVABLE))
     {
+      G_READ_UNLOCK (&type_rw_lock);
       g_warning ("cannot derive `%s' from non-fundamental parent type `%s'",
                 type_name,
                 NODE_NAME (pnode));
       return FALSE;
     }
+  G_READ_UNLOCK (&type_rw_lock);
   
   return TRUE;
 }
 
 static gboolean
-check_value_table (const gchar           *type_name,
-                  const GTypeValueTable *value_table)
+check_value_table_I (const gchar           *type_name,
+                    const GTypeValueTable *value_table)
 {
   if (!value_table)
     return FALSE;
@@ -497,7 +552,6 @@ check_value_table (const gchar           *type_name,
          value_table->lcopy_type || value_table->lcopy_value)
        g_warning ("cannot handle uninitializable values of type `%s'",
                   type_name);
-
       return FALSE;
     }
   else /* value_table->value_init != NULL */
@@ -529,19 +583,18 @@ check_value_table (const gchar           *type_name,
          return FALSE;
        }
     }
-
   return TRUE;
 }
 
 static gboolean
-check_type_info (TypeNode        *pnode,
-                GType            ftype,
-                const gchar     *type_name,
-                const GTypeInfo *info)
+check_type_info_L (TypeNode        *pnode,
+                  GType            ftype,
+                  const gchar     *type_name,
+                  const GTypeInfo *info)
 {
-  GTypeFundamentalInfo *finfo = type_node_fundamental_info (LOOKUP_TYPE_NODE (ftype));
+  GTypeFundamentalInfo *finfo = type_node_fundamental_info_L (lookup_type_node_L (ftype));
   gboolean is_interface = G_TYPE_IS_INTERFACE (ftype);
-
+  
   /* check instance members */
   if (!(finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
       (info->instance_size || info->n_preallocs || info->instance_init))
@@ -612,49 +665,49 @@ check_type_info (TypeNode        *pnode,
          return FALSE;
        }
     }
-
+  
   return TRUE;
 }
 
 static TypeNode*
-find_conforming_type (TypeNode *pnode,
-                     TypeNode *iface)
+find_conforming_type_L (TypeNode *pnode,
+                       TypeNode *iface)
 {
   TypeNode *node = NULL;
   guint i;
-
-  if (type_lookup_iface_entry (pnode, iface))
+  
+  if (type_lookup_iface_entry_L (pnode, iface))
     return pnode;
-
+  
   for (i = 0; i < pnode->n_children && !node; i++)
-    node = find_conforming_type (LOOKUP_TYPE_NODE (pnode->children[i]), iface);
-
+    node = find_conforming_type_L (lookup_type_node_L (pnode->children[i]), iface);
+  
   return node;
 }
 
 static gboolean
-check_add_interface (GType instance_type,
-                    GType iface_type)
+check_add_interface_L (GType instance_type,
+                      GType iface_type)
 {
-  TypeNode *node = LOOKUP_TYPE_NODE (instance_type);
-  TypeNode *iface = LOOKUP_TYPE_NODE (iface_type);
+  TypeNode *node = lookup_type_node_L (instance_type);
+  TypeNode *iface = lookup_type_node_L (iface_type);
   TypeNode *tnode;
-
+  
   if (!node || !node->is_instantiatable)
     {
       g_warning ("cannot add interfaces to invalid (non-instantiatable) type `%s'",
-                type_descriptive_name (instance_type));
+                type_descriptive_name_L (instance_type));
       return FALSE;
     }
   if (!iface || !iface->is_iface)
     {
       g_warning ("cannot add invalid (non-interface) type `%s' to type `%s'",
-                type_descriptive_name (iface_type),
+                type_descriptive_name_L (iface_type),
                 NODE_NAME (node));
       return FALSE;
     }
-  tnode = LOOKUP_TYPE_NODE (NODE_PARENT_TYPE (iface));
-  if (NODE_PARENT_TYPE (tnode) && !type_lookup_iface_entry (node, tnode))
+  tnode = lookup_type_node_L (NODE_PARENT_TYPE (iface));
+  if (NODE_PARENT_TYPE (tnode) && !type_lookup_iface_entry_L (node, tnode))
     {
       g_warning ("cannot add sub-interface `%s' to type `%s' which does not conform to super-interface `%s'",
                 NODE_NAME (iface),
@@ -662,7 +715,7 @@ check_add_interface (GType instance_type,
                 NODE_NAME (tnode));
       return FALSE;
     }
-  tnode = find_conforming_type (node, iface);
+  tnode = find_conforming_type_L (node, iface);
   if (tnode)
     {
       g_warning ("cannot add interface type `%s' to type `%s', since type `%s' already conforms to interface",
@@ -671,51 +724,30 @@ check_add_interface (GType instance_type,
                 NODE_NAME (tnode));
       return FALSE;
     }
-
   return TRUE;
 }
 
 static gboolean
-check_interface_info (TypeNode             *iface,
-                     GType                 instance_type,
-                     const GInterfaceInfo *info)
+check_interface_info_L (TypeNode             *iface,
+                       GType                 instance_type,
+                       const GInterfaceInfo *info)
 {
   if ((info->interface_finalize || info->interface_data) && !info->interface_init)
     {
       g_warning ("interface type `%s' for type `%s' comes without initializer",
                 NODE_NAME (iface),
-                type_descriptive_name (instance_type));
+                type_descriptive_name_L (instance_type));
       return FALSE;
     }
-
+  
   return TRUE;
 }
 
-
 /* --- type info (type node data) --- */
 static void
-type_add_flags (TypeNode  *node,
-               GTypeFlags flags)
-{
-  guint dflags;
-
-  g_return_if_fail ((flags & ~TYPE_FLAG_MASK) == 0);
-  g_return_if_fail (node != NULL);
-
-  if (!quark_type_flags)
-    quark_type_flags = g_quark_from_static_string ("GTypeFlags");
-  if ((flags & G_TYPE_FLAG_ABSTRACT) && node->is_classed &&
-      node->data && node->data->class.class)
-    g_warning ("tagging type `%s' as abstract after class initialization", NODE_NAME (node));
-  dflags = GPOINTER_TO_UINT (g_type_get_qdata (NODE_TYPE (node), quark_type_flags));
-  dflags |= flags;
-  g_type_set_qdata (NODE_TYPE (node), quark_type_flags, GUINT_TO_POINTER (dflags));
-}
-
-static void
-type_data_make (TypeNode              *node,
-               const GTypeInfo       *info,
-               const GTypeValueTable *value_table)
+type_data_make_W (TypeNode              *node,
+                 const GTypeInfo       *info,
+                 const GTypeValueTable *value_table)
 {
   TypeData *data;
   GTypeValueTable *vtable = NULL;
@@ -725,7 +757,7 @@ type_data_make (TypeNode              *node,
   
   if (!value_table)
     {
-      TypeNode *pnode = LOOKUP_TYPE_NODE (NODE_PARENT_TYPE (node));
+      TypeNode *pnode = lookup_type_node_L (NODE_PARENT_TYPE (node));
       
       if (pnode)
        vtable = pnode->data->common.value_table;
@@ -795,46 +827,57 @@ type_data_make (TypeNode              *node,
   if (vtable_size)
     *vtable = *value_table;
   node->data->common.value_table = vtable;
-
+  
   g_assert (node->data->common.value_table != NULL); /* paranoid */
 }
 
 static inline void
-type_data_ref (TypeNode *node)
+type_data_ref_Wm (TypeNode *node)
 {
   if (!node->data)
     {
-      TypeNode *pnode = LOOKUP_TYPE_NODE (NODE_PARENT_TYPE (node));
+      TypeNode *pnode = lookup_type_node_L (NODE_PARENT_TYPE (node));
       GTypeInfo tmp_info;
       GTypeValueTable tmp_value_table;
       
       g_assert (node->plugin != NULL);
       
       if (pnode)
-       type_data_ref (pnode);
+       {
+         type_data_ref_Wm (pnode);
+         if (node->data)
+           INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
+       }
       
       memset (&tmp_info, 0, sizeof (tmp_info));
       memset (&tmp_value_table, 0, sizeof (tmp_value_table));
+      
+      G_WRITE_UNLOCK (&type_rw_lock);
       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,
-                     check_value_table (NODE_NAME (node), &tmp_value_table) ? &tmp_value_table : NULL);
+      G_WRITE_LOCK (&type_rw_lock);
+      if (node->data)
+       INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
+      
+      check_type_info_L (pnode, G_TYPE_FUNDAMENTAL (NODE_TYPE (node)), NODE_NAME (node), &tmp_info);
+      type_data_make_W (node, &tmp_info,
+                       check_value_table_I (NODE_NAME (node),
+                                            &tmp_value_table) ? &tmp_value_table : NULL);
     }
   else
     {
       g_assert (node->data->common.ref_count > 0);
-
+      
       node->data->common.ref_count += 1;
     }
 }
 
 static inline void
-type_data_unref (TypeNode *node,
-                gboolean  uncached)
+type_data_unref_Wm (TypeNode *node,
+                   gboolean  uncached)
 {
   g_assert (node->data && node->data->common.ref_count);
-
+  
   if (node->data->common.ref_count > 1)
     node->data->common.ref_count -= 1;
   else
@@ -845,20 +888,20 @@ type_data_unref (TypeNode *node,
                     NODE_NAME (node));
          return;
        }
-
-      type_data_last_unref (NODE_TYPE (node), uncached);
+      
+      type_data_last_unref_Wm (NODE_TYPE (node), uncached);
     }
 }
 
 static void
-type_node_add_iface_entry (TypeNode *node,
-                          GType     iface_type)
+type_node_add_iface_entry_W (TypeNode *node,
+                            GType     iface_type)
 {
   IFaceEntry *entries;
   guint i;
-
+  
   g_assert (node->is_instantiatable && node->n_ifaces < MAX_N_IFACES);
-
+  
   node->n_ifaces++;
   node->private.iface_entries = g_renew (IFaceEntry, node->private.iface_entries, node->n_ifaces);
   entries = node->private.iface_entries;
@@ -868,16 +911,16 @@ type_node_add_iface_entry (TypeNode *node,
   g_memmove (entries + i + 1, entries + i, sizeof (entries[0]) * (node->n_ifaces - i - 1));
   entries[i].iface_type = iface_type;
   entries[i].vtable = NULL;
-
+  
   for (i = 0; i < node->n_children; i++)
-    type_node_add_iface_entry (LOOKUP_TYPE_NODE (node->children[i]), iface_type);
+    type_node_add_iface_entry_W (lookup_type_node_L (node->children[i]), iface_type);
 }
 
 static void
-type_add_interface (TypeNode             *node,
-                   TypeNode             *iface,
-                   const GInterfaceInfo *info,
-                   GTypePlugin          *plugin)
+type_add_interface_W (TypeNode             *node,
+                     TypeNode             *iface,
+                     const GInterfaceInfo *info,
+                     GTypePlugin          *plugin)
 {
   IFaceHolder *iholder = g_new0 (IFaceHolder, 1);
   
@@ -891,33 +934,41 @@ type_add_interface (TypeNode             *node,
   iholder->instance_type = NODE_TYPE (node);
   iholder->info = info ? g_memdup (info, sizeof (*info)) : NULL;
   iholder->plugin = plugin;
-
-  type_node_add_iface_entry (node, NODE_TYPE (iface));
+  
+  type_node_add_iface_entry_W (node, NODE_TYPE (iface));
 }
 
 static IFaceHolder*
-type_iface_retrive_holder_info (TypeNode *iface,
-                               GType     instance_type)
+type_iface_retrive_holder_info_Wm (TypeNode *iface,
+                                  GType     instance_type)
 {
   IFaceHolder *iholder = iface->private.iface_conformants;
-
+  
   g_assert (iface->is_iface);
-
+  
   while (iholder->instance_type != instance_type)
     iholder = iholder->next;
-
+  
   if (!iholder->info)
     {
       GInterfaceInfo tmp_info;
       
       g_assert (iholder->plugin != NULL);
       
-      type_data_ref (iface);
-
+      type_data_ref_Wm (iface);
+      if (iholder->info)
+       INVALID_RECURSION ("g_type_plugin_*", iface->plugin, NODE_NAME (iface));
+      
       memset (&tmp_info, 0, sizeof (tmp_info));
+      
+      G_WRITE_UNLOCK (&type_rw_lock);
       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);
+      G_WRITE_LOCK (&type_rw_lock);
+      if (iholder->info)
+        INVALID_RECURSION ("g_type_plugin_*", iholder->plugin, NODE_NAME (iface));
+      
+      check_interface_info_L (iface, instance_type, &tmp_info);
       iholder->info = g_memdup (&tmp_info, sizeof (tmp_info));
     }
   
@@ -925,23 +976,26 @@ type_iface_retrive_holder_info (TypeNode *iface,
 }
 
 static void
-type_iface_blow_holder_info (TypeNode *iface,
-                            GType     instance_type)
+type_iface_blow_holder_info_Wm (TypeNode *iface,
+                               GType     instance_type)
 {
   IFaceHolder *iholder = iface->private.iface_conformants;
-
+  
   g_assert (iface->is_iface);
-
+  
   while (iholder->instance_type != instance_type)
     iholder = iholder->next;
-
+  
   if (iholder->info && iholder->plugin)
     {
       g_free (iholder->info);
       iholder->info = NULL;
+      
+      G_WRITE_UNLOCK (&type_rw_lock);
       g_type_plugin_unuse (iholder->plugin);
-
-      type_data_unref (iface, FALSE);
+      G_WRITE_LOCK (&type_rw_lock);
+      
+      type_data_unref_Wm (iface, FALSE);
     }
 }
 
@@ -950,21 +1004,25 @@ type_iface_blow_holder_info (TypeNode *iface,
 GTypeInstance*
 g_type_create_instance (GType type)
 {
-  TypeNode *node = LOOKUP_TYPE_NODE (type);
+  TypeNode *node;
   GTypeInstance *instance;
   GTypeClass *class;
   guint i;
   
+  G_READ_LOCK (&type_rw_lock);
+  node = lookup_type_node_L (type);
+  G_READ_UNLOCK (&type_rw_lock);
   if (!node || !node->is_instantiatable)
     {
       g_warning ("cannot create new instance of invalid (non-instantiatable) type `%s'",
-                type_descriptive_name (type));
+                type_descriptive_name_U (type));
       return NULL;
     }
+  /* G_TYPE_IS_ABSTRACT() is an external call: _U */
   if (G_TYPE_IS_ABSTRACT (type))
     {
       g_warning ("cannot create instance of abstract (non-instantiatable) type `%s'",
-                type_descriptive_name (type));
+                type_descriptive_name_U (type));
       return NULL;
     }
   
@@ -972,6 +1030,7 @@ g_type_create_instance (GType type)
   
   if (node->data->instance.n_preallocs)
     {
+      G_WRITE_LOCK (&type_rw_lock);
       if (!node->data->instance.mem_chunk)
        node->data->instance.mem_chunk = g_mem_chunk_new (NODE_NAME (node),
                                                          node->data->instance.instance_size,
@@ -979,13 +1038,17 @@ g_type_create_instance (GType type)
                                                           node->data->instance.n_preallocs),
                                                          G_ALLOC_AND_FREE);
       instance = g_chunk_new0 (GTypeInstance, node->data->instance.mem_chunk);
+      G_WRITE_UNLOCK (&type_rw_lock);
     }
   else
-    instance = g_malloc0 (node->data->instance.instance_size);
-  
+    instance = g_malloc0 (node->data->instance.instance_size); /* fine without read lock */
   for (i = node->n_supers; i > 0; i--)
     {
-      TypeNode *pnode = LOOKUP_TYPE_NODE (node->supers[i]);
+      TypeNode *pnode;
+      
+      G_READ_LOCK (&type_rw_lock);
+      pnode = lookup_type_node_L (node->supers[i]);
+      G_READ_UNLOCK (&type_rw_lock);
       
       if (pnode->data->instance.instance_init)
        {
@@ -994,9 +1057,10 @@ g_type_create_instance (GType type)
        }
     }
   instance->g_class = class;
+  
   if (node->data->instance.instance_init)
     node->data->instance.instance_init (instance, class);
-
+  
   return instance;
 }
 
@@ -1005,102 +1069,119 @@ g_type_free_instance (GTypeInstance *instance)
 {
   TypeNode *node;
   GTypeClass *class;
-
+  
   g_return_if_fail (instance != NULL && instance->g_class != NULL);
-
+  
+  G_READ_LOCK (&type_rw_lock);
   class = instance->g_class;
-  node = LOOKUP_TYPE_NODE (class->g_type);
+  node = lookup_type_node_L (class->g_type);
   if (!node || !node->is_instantiatable || !node->data || node->data->class.class != (gpointer) class)
     {
       g_warning ("cannot free instance of invalid (non-instantiatable) type `%s'",
-                type_descriptive_name (class->g_type));
+                type_descriptive_name_L (class->g_type));
+      G_READ_UNLOCK (&type_rw_lock);
       return;
     }
+  G_READ_UNLOCK (&type_rw_lock);
+  /* G_TYPE_IS_ABSTRACT() is an external call: _U */
   if (G_TYPE_IS_ABSTRACT (NODE_TYPE (node)))
     {
       g_warning ("cannot free instance of abstract (non-instantiatable) type `%s'",
                 NODE_NAME (node));
       return;
     }
-
+  
   instance->g_class = NULL;
   memset (instance, 0xaa, node->data->instance.instance_size); // FIXME: debugging hack
   if (node->data->instance.n_preallocs)
-    g_chunk_free (instance, node->data->instance.mem_chunk);
+    {
+      G_WRITE_LOCK (&type_rw_lock);
+      g_chunk_free (instance, node->data->instance.mem_chunk);
+      G_WRITE_UNLOCK (&type_rw_lock);
+    }
   else
     g_free (instance);
-
+  
   g_type_class_unref (class);
 }
 
 static void
-type_propagate_iface_vtable (TypeNode       *pnode,
-                            TypeNode       *iface,
-                            GTypeInterface *vtable)
+type_propagate_iface_vtable_W (TypeNode       *pnode,
+                              TypeNode       *iface,
+                              GTypeInterface *vtable)
 {
-  IFaceEntry *entry = type_lookup_iface_entry (pnode, iface);
+  IFaceEntry *entry = type_lookup_iface_entry_L (pnode, iface);
   guint i;
-
+  
   entry->vtable = vtable;
   for (i = 0; i < pnode->n_children; i++)
     {
-      TypeNode *node = LOOKUP_TYPE_NODE (pnode->children[i]);
-
-      type_propagate_iface_vtable (node, iface, vtable);
+      TypeNode *node = lookup_type_node_L (pnode->children[i]);
+      
+      type_propagate_iface_vtable_W (node, iface, vtable);
     }
 }
 
 static void
-type_iface_vtable_init (TypeNode       *iface,
-                       TypeNode       *node)
+type_iface_vtable_init_Wm (TypeNode *iface,
+                          TypeNode *node)
 {
-  IFaceEntry *entry = type_lookup_iface_entry (node, iface);
-  IFaceHolder *iholder = type_iface_retrive_holder_info (iface, NODE_TYPE (node));
+  IFaceEntry *entry = type_lookup_iface_entry_L (node, iface);
+  IFaceHolder *iholder = type_iface_retrive_holder_info_Wm (iface, NODE_TYPE (node));
   GTypeInterface *vtable;
   
   g_assert (iface->data && entry && entry->vtable == NULL && iholder && iholder->info);
-
+  
   vtable = g_malloc0 (iface->data->iface.vtable_size);
-  type_propagate_iface_vtable (node, iface, vtable);
+  type_propagate_iface_vtable_W (node, iface, vtable);
   vtable->g_type = NODE_TYPE (iface);
   vtable->g_instance_type = NODE_TYPE (node);
-
-  if (iface->data->iface.vtable_init_base)
-    iface->data->iface.vtable_init_base (vtable);
-  if (iholder->info->interface_init)
-    iholder->info->interface_init (vtable, iholder->info->interface_data);
+  
+  if (iface->data->iface.vtable_init_base || iholder->info->interface_init)
+    {
+      G_WRITE_UNLOCK (&type_rw_lock);
+      if (iface->data->iface.vtable_init_base)
+       iface->data->iface.vtable_init_base (vtable);
+      if (iholder->info->interface_init)
+       iholder->info->interface_init (vtable, iholder->info->interface_data);
+      G_WRITE_LOCK (&type_rw_lock);
+    }
 }
 
 static void
-type_iface_vtable_finalize (TypeNode       *iface,
-                           TypeNode       *node,
-                           GTypeInterface *vtable)
+type_iface_vtable_finalize_Wm (TypeNode       *iface,
+                              TypeNode       *node,
+                              GTypeInterface *vtable)
 {
-  IFaceEntry *entry = type_lookup_iface_entry (node, iface);
+  IFaceEntry *entry = type_lookup_iface_entry_L (node, iface);
   IFaceHolder *iholder = iface->private.iface_conformants;
-
+  
   g_assert (entry && entry->vtable == vtable);
-
+  
   while (iholder->instance_type != NODE_TYPE (node))
     iholder = iholder->next;
   g_assert (iholder && iholder->info);
-
-  type_propagate_iface_vtable (node, iface, NULL);
-  if (iholder->info->interface_finalize)
-    iholder->info->interface_finalize (vtable, iholder->info->interface_data);
-  if (iface->data->iface.vtable_finalize_base)
-    iface->data->iface.vtable_finalize_base (vtable);
   
+  type_propagate_iface_vtable_W (node, iface, NULL);
+  if (iholder->info->interface_finalize || iface->data->iface.vtable_finalize_base)
+    {
+      G_WRITE_UNLOCK (&type_rw_lock);
+      if (iholder->info->interface_finalize)
+       iholder->info->interface_finalize (vtable, iholder->info->interface_data);
+      if (iface->data->iface.vtable_finalize_base)
+       iface->data->iface.vtable_finalize_base (vtable);
+      G_WRITE_LOCK (&type_rw_lock);
+    }
   vtable->g_type = 0;
   vtable->g_instance_type = 0;
   g_free (vtable);
-
-  type_iface_blow_holder_info (iface, NODE_TYPE (node));
+  
+  type_iface_blow_holder_info_Wm (iface, NODE_TYPE (node));
 }
 
 static void
-type_class_init (TypeNode   *node,
-                GTypeClass *pclass)
+type_class_init_Wm (TypeNode   *node,
+                   GTypeClass *pclass)
 {
   GSList *slist, *init_slist = NULL;
   GTypeClass *class;
@@ -1117,19 +1198,22 @@ type_class_init (TypeNode   *node,
   
   if (pclass)
     {
-      TypeNode *pnode = LOOKUP_TYPE_NODE (pclass->g_type);
+      TypeNode *pnode = lookup_type_node_L (pclass->g_type);
       
       memcpy (class, pclass, pnode->data->class.class_size);
     }
-  
   class->g_type = NODE_TYPE (node);
   
+  G_WRITE_UNLOCK (&type_rw_lock);
+  
   /* stack all base class initialization functions, so we
    * call them in ascending order.
    */
-  for (bnode = node; bnode; bnode = LOOKUP_TYPE_NODE (NODE_PARENT_TYPE (bnode)))
+  G_READ_LOCK (&type_rw_lock);
+  for (bnode = node; bnode; bnode = lookup_type_node_L (NODE_PARENT_TYPE (bnode)))
     if (bnode->data->class.class_init_base)
       init_slist = g_slist_prepend (init_slist, (gpointer) bnode->data->class.class_init_base);
+  G_READ_UNLOCK (&type_rw_lock);
   for (slist = init_slist; slist; slist = slist->next)
     {
       GBaseInitFunc class_init_base = (GBaseInitFunc) slist->data;
@@ -1140,14 +1224,16 @@ type_class_init (TypeNode   *node,
   
   if (node->data->class.class_init)
     node->data->class.class_init (class, (gpointer) node->data->class.class_data);
-
+  
+  G_WRITE_LOCK (&type_rw_lock);
+  
   /* ok, we got the class done, now initialize all interfaces */
   for (entry = NULL, i = 0; i < node->n_ifaces; i++)
     if (!node->private.iface_entries[i].vtable)
       entry = node->private.iface_entries + i;
   while (entry)
     {
-      type_iface_vtable_init (LOOKUP_TYPE_NODE (entry->iface_type), node);
+      type_iface_vtable_init_Wm (lookup_type_node_L (entry->iface_type), node);
       
       for (entry = NULL, i = 0; i < node->n_ifaces; i++)
        if (!node->private.iface_entries[i].vtable)
@@ -1156,7 +1242,7 @@ type_class_init (TypeNode   *node,
 }
 
 static void
-type_data_finalize_class_ifaces (TypeNode *node)
+type_data_finalize_class_ifaces_Wm (TypeNode *node)
 {
   IFaceEntry *entry;
   guint i;
@@ -1164,8 +1250,8 @@ type_data_finalize_class_ifaces (TypeNode *node)
   g_assert (node->is_instantiatable && node->data && node->data->class.class && node->data->common.ref_count == 0);
   
   g_message ("finalizing interfaces for %sClass `%s'",
-            type_descriptive_name (G_TYPE_FUNDAMENTAL (NODE_TYPE (node))),
-            type_descriptive_name (NODE_TYPE (node)));
+            type_descriptive_name_L (G_TYPE_FUNDAMENTAL (NODE_TYPE (node))),
+            type_descriptive_name_L (NODE_TYPE (node)));
   
   for (entry = NULL, i = 0; i < node->n_ifaces; i++)
     if (node->private.iface_entries[i].vtable &&
@@ -1173,7 +1259,7 @@ type_data_finalize_class_ifaces (TypeNode *node)
       entry = node->private.iface_entries + i;
   while (entry)
     {
-      type_iface_vtable_finalize (LOOKUP_TYPE_NODE (entry->iface_type), node, entry->vtable);
+      type_iface_vtable_finalize_Wm (lookup_type_node_L (entry->iface_type), node, entry->vtable);
       
       for (entry = NULL, i = 0; i < node->n_ifaces; i++)
        if (node->private.iface_entries[i].vtable &&
@@ -1183,8 +1269,8 @@ type_data_finalize_class_ifaces (TypeNode *node)
 }
 
 static void
-type_data_finalize_class (TypeNode  *node,
-                         ClassData *cdata)
+type_data_finalize_class_U (TypeNode  *node,
+                           ClassData *cdata)
 {
   GTypeClass *class = cdata->class;
   TypeNode *bnode;
@@ -1192,9 +1278,9 @@ type_data_finalize_class (TypeNode  *node,
   g_assert (cdata->class && cdata->common.ref_count == 0);
   
   g_message ("finalizing %sClass `%s'",
-            type_descriptive_name (G_TYPE_FUNDAMENTAL (NODE_TYPE (node))),
-            type_descriptive_name (NODE_TYPE (node)));
-
+            type_descriptive_name_U (G_TYPE_FUNDAMENTAL (NODE_TYPE (node))),
+            type_descriptive_name_U (NODE_TYPE (node)));
+  
   if (cdata->class_finalize)
     cdata->class_finalize (class, (gpointer) cdata->class_data);
   
@@ -1202,38 +1288,59 @@ type_data_finalize_class (TypeNode  *node,
    */
   if (cdata->class_finalize_base)
     cdata->class_finalize_base (class);
-  for (bnode = LOOKUP_TYPE_NODE (NODE_PARENT_TYPE (node)); bnode; bnode = LOOKUP_TYPE_NODE (NODE_PARENT_TYPE (bnode)))
+  G_READ_LOCK (&type_rw_lock);
+  for (bnode = lookup_type_node_L (NODE_PARENT_TYPE (node)); bnode; bnode = lookup_type_node_L (NODE_PARENT_TYPE (bnode)))
     if (bnode->data->class.class_finalize_base)
-      bnode->data->class.class_finalize_base (class);
+      {
+       G_READ_UNLOCK (&type_rw_lock);
+       bnode->data->class.class_finalize_base (class);
+       G_READ_LOCK (&type_rw_lock);
+      }
+  G_READ_UNLOCK (&type_rw_lock);
   
   class->g_type = 0;
   g_free (cdata->class);
 }
 
 static void
-type_data_last_unref (GType    type,
-                     gboolean uncached)
+type_data_last_unref_Wm (GType    type,
+                        gboolean uncached)
 {
-  TypeNode *node = LOOKUP_TYPE_NODE (type);
-
+  TypeNode *node = lookup_type_node_L (type);
+  
   g_return_if_fail (node != NULL && node->plugin != NULL);
   
   if (!node->data || node->data->common.ref_count == 0)
     {
       g_warning ("cannot drop last reference to unreferenced type `%s'",
-                type_descriptive_name (type));
+                type_descriptive_name_U (type));
       return;
     }
-
-  if (node->is_classed && node->data && node->data->class.class)
+  
+  if (node->is_classed && node->data && node->data->class.class && static_n_class_cache_funcs)
     {
       guint i;
-
-      for (i = 0; i < n_class_cache_funcs; i++)
-       if (class_cache_funcs[i].cache_func (class_cache_funcs[i].cache_data, node->data->class.class))
-         break;
+      
+      G_WRITE_UNLOCK (&type_rw_lock);
+      G_READ_LOCK (&type_rw_lock);
+      for (i = 0; i < static_n_class_cache_funcs; i++)
+       {
+         GTypeClassCacheFunc cache_func = static_class_cache_funcs[i].cache_func;
+         gpointer cache_data = static_class_cache_funcs[i].cache_data;
+         gboolean need_break;
+         
+         G_READ_UNLOCK (&type_rw_lock);
+         need_break = cache_func (cache_data, node->data->class.class);
+         G_READ_LOCK (&type_rw_lock);
+         if (!node->data || node->data->common.ref_count == 0)
+           INVALID_RECURSION ("GType class cache function ", cache_func, NODE_NAME (node));
+         if (need_break)
+           break;
+       }
+      G_READ_UNLOCK (&type_rw_lock);
+      G_WRITE_LOCK (&type_rw_lock);
     }
-
+  
   if (node->data->common.ref_count > 1)        /* may have been re-referenced meanwhile */
     node->data->common.ref_count -= 1;
   else
@@ -1253,18 +1360,22 @@ type_data_last_unref (GType    type,
       if (node->is_classed && tdata->class.class)
        {
          if (node->n_ifaces)
-           type_data_finalize_class_ifaces (node);
+           type_data_finalize_class_ifaces_Wm (node);
          node->data = NULL;
-         type_data_finalize_class (node, &tdata->class);
+         G_WRITE_UNLOCK (&type_rw_lock);
+         type_data_finalize_class_U (node, &tdata->class);
+         G_WRITE_LOCK (&type_rw_lock);
        }
       else
        node->data = NULL;
-
+      
       g_free (tdata);
       
       if (ptype)
-       type_data_unref (LOOKUP_TYPE_NODE (ptype), FALSE);
+       type_data_unref_Wm (lookup_type_node_L (ptype), FALSE);
+      G_WRITE_UNLOCK (&type_rw_lock);
       g_type_plugin_unuse (node->plugin);
+      G_WRITE_LOCK (&type_rw_lock);
     }
 }
 
@@ -1273,38 +1384,44 @@ g_type_add_class_cache_func (gpointer            cache_data,
                             GTypeClassCacheFunc cache_func)
 {
   guint i;
-
+  
   g_return_if_fail (cache_func != NULL);
-
-  i = n_class_cache_funcs++;
-  class_cache_funcs = g_renew (ClassCacheFunc, class_cache_funcs, n_class_cache_funcs);
-  class_cache_funcs[i].cache_data = cache_data;
-  class_cache_funcs[i].cache_func = cache_func;
+  
+  G_WRITE_LOCK (&type_rw_lock);
+  i = static_n_class_cache_funcs++;
+  static_class_cache_funcs = g_renew (ClassCacheFunc, static_class_cache_funcs, static_n_class_cache_funcs);
+  static_class_cache_funcs[i].cache_data = cache_data;
+  static_class_cache_funcs[i].cache_func = cache_func;
+  G_WRITE_UNLOCK (&type_rw_lock);
 }
 
 void
 g_type_remove_class_cache_func (gpointer            cache_data,
                                GTypeClassCacheFunc cache_func)
 {
+  gboolean found_it = FALSE;
   guint i;
-
+  
   g_return_if_fail (cache_func != NULL);
-
-  for (i = 0; i < n_class_cache_funcs; i++)
-    if (class_cache_funcs[i].cache_data == cache_data &&
-       class_cache_funcs[i].cache_func == cache_func)
+  
+  G_WRITE_LOCK (&type_rw_lock);
+  for (i = 0; i < static_n_class_cache_funcs; i++)
+    if (static_class_cache_funcs[i].cache_data == cache_data &&
+       static_class_cache_funcs[i].cache_func == cache_func)
       {
-       n_class_cache_funcs--;
-       g_memmove (class_cache_funcs + i,
-                  class_cache_funcs + i + 1,
-                  sizeof (class_cache_funcs[0]) * (n_class_cache_funcs - i));
-       class_cache_funcs = g_renew (ClassCacheFunc, class_cache_funcs, n_class_cache_funcs);
-
-       return;
+       static_n_class_cache_funcs--;
+       g_memmove (static_class_cache_funcs + i,
+                  static_class_cache_funcs + i + 1,
+                  sizeof (static_class_cache_funcs[0]) * (static_n_class_cache_funcs - i));
+       static_class_cache_funcs = g_renew (ClassCacheFunc, static_class_cache_funcs, static_n_class_cache_funcs);
+       found_it = TRUE;
+       break;
       }
-
-  g_warning (G_STRLOC ": cannot remove unregistered class cache func %p with data %p",
-            cache_func, cache_data);
+  G_WRITE_UNLOCK (&type_rw_lock);
+  
+  if (!found_it)
+    g_warning (G_STRLOC ": cannot remove unregistered class cache func %p with data %p",
+              cache_func, cache_data);
 }
 
 
@@ -1318,13 +1435,13 @@ g_type_register_fundamental (GType                       type_id,
 {
   GTypeFundamentalInfo *node_finfo;
   TypeNode *node;
-
+  
   g_return_val_if_fail (type_id > 0, 0);
   g_return_val_if_fail (type_name != NULL, 0);
   g_return_val_if_fail (info != NULL, 0);
   g_return_val_if_fail (finfo != NULL, 0);
-
-  if (!check_type_name (type_name))
+  
+  if (!check_type_name_U (type_name))
     return 0;
   if (G_TYPE_FUNDAMENTAL (type_id) != type_id)
     {
@@ -1333,30 +1450,32 @@ g_type_register_fundamental (GType                       type_id,
                 type_id);
       return 0;
     }
-  if (LOOKUP_TYPE_NODE (type_id))
+  if ((finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
+      !(finfo->type_flags & G_TYPE_FLAG_CLASSED))
     {
-      g_warning ("cannot register existing fundamental type `%s' (as `%s')",
-                type_descriptive_name (type_id),
+      g_warning ("cannot register instantiatable fundamental type `%s' as non-classed",
                 type_name);
       return 0;
     }
-  if ((finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) &&
-      !(finfo->type_flags & G_TYPE_FLAG_CLASSED))
+  G_WRITE_LOCK (&type_rw_lock);
+  if (lookup_type_node_L (type_id))
     {
-      g_warning ("cannot register instantiatable fundamental type `%s' as non-classed",
+      G_WRITE_UNLOCK (&type_rw_lock);
+      g_warning ("cannot register existing fundamental type `%s' (as `%s')",
+                type_descriptive_name_U (type_id),
                 type_name);
       return 0;
     }
-
-  node = type_node_fundamental_new (type_id, type_name, finfo->type_flags);
-  node_finfo = type_node_fundamental_info (node);
-  type_add_flags (node, flags);
-
-  if (!check_type_info (NULL, G_TYPE_FUNDAMENTAL (NODE_TYPE (node)), type_name, info))
-    return NODE_TYPE (node);
-  type_data_make (node, info,
-                 check_value_table (type_name, info->value_table) ? info->value_table : NULL);
-
+  
+  node = type_node_fundamental_new_W (type_id, type_name, finfo->type_flags);
+  node_finfo = type_node_fundamental_info_L (node);
+  type_add_flags_W (node, flags);
+  
+  if (check_type_info_L (NULL, G_TYPE_FUNDAMENTAL (NODE_TYPE (node)), type_name, info))
+    type_data_make_W (node, info,
+                     check_value_table_I (type_name, info->value_table) ? info->value_table : NULL);
+  G_WRITE_UNLOCK (&type_rw_lock);
+  
   return NODE_TYPE (node);
 }
 
@@ -1367,21 +1486,14 @@ g_type_register_static (GType            parent_type,
                        GTypeFlags       flags)
 {
   TypeNode *pnode, *node;
-  GType type;
+  GType type = 0;
   
   g_return_val_if_fail (parent_type > 0, 0);
   g_return_val_if_fail (type_name != NULL, 0);
   g_return_val_if_fail (info != NULL, 0);
   
-  if (!check_type_name (type_name))
-    return 0;
-  if (!check_derivation (parent_type, type_name))
-    return 0;
-
-  pnode = LOOKUP_TYPE_NODE (parent_type);
-  type_data_ref (pnode);
-
-  if (!check_type_info (pnode, G_TYPE_FUNDAMENTAL (parent_type), type_name, info))
+  if (!check_type_name_U (type_name) ||
+      !check_derivation_U (parent_type, type_name))
     return 0;
   if (info->class_finalize)
     {
@@ -1389,13 +1501,20 @@ g_type_register_static (GType            parent_type,
                 type_name);
       return 0;
     }
-
-  node = type_node_new (pnode, type_name, NULL);
-  type_add_flags (node, flags);
-  type = NODE_TYPE (node);
-  type_data_make (node, info,
-                 check_value_table (type_name, info->value_table) ? info->value_table : NULL);
-
+  
+  G_WRITE_LOCK (&type_rw_lock);
+  pnode = lookup_type_node_L (parent_type);
+  type_data_ref_Wm (pnode);
+  if (check_type_info_L (pnode, G_TYPE_FUNDAMENTAL (parent_type), type_name, info))
+    {
+      node = type_node_new_W (pnode, type_name, NULL);
+      type_add_flags_W (node, flags);
+      type = NODE_TYPE (node);
+      type_data_make_W (node, info,
+                       check_value_table_I (type_name, info->value_table) ? info->value_table : NULL);
+    }
+  G_WRITE_UNLOCK (&type_rw_lock);
+  
   return type;
 }
 
@@ -1407,23 +1526,23 @@ g_type_register_dynamic (GType        parent_type,
 {
   TypeNode *pnode, *node;
   GType type;
-
+  
   g_return_val_if_fail (parent_type > 0, 0);
   g_return_val_if_fail (type_name != NULL, 0);
   g_return_val_if_fail (plugin != NULL, 0);
-
-  if (!check_type_name (type_name))
-    return 0;
-  if (!check_derivation (parent_type, type_name))
-    return 0;
-  if (!check_plugin (plugin, TRUE, FALSE, type_name))
+  
+  if (!check_type_name_U (type_name) ||
+      !check_derivation_U (parent_type, type_name) ||
+      !check_plugin_U (plugin, TRUE, FALSE, type_name))
     return 0;
-  pnode = LOOKUP_TYPE_NODE (parent_type);
-
-  node = type_node_new (pnode, type_name, plugin);
-  type_add_flags (node, flags);
+  
+  G_WRITE_LOCK (&type_rw_lock);
+  pnode = lookup_type_node_L (parent_type);
+  node = type_node_new_W (pnode, type_name, plugin);
+  type_add_flags_W (node, flags);
   type = NODE_TYPE (node);
-
+  G_WRITE_UNLOCK (&type_rw_lock);
+  
   return type;
 }
 
@@ -1432,19 +1551,20 @@ g_type_add_interface_static (GType                 instance_type,
                             GType                 interface_type,
                             const GInterfaceInfo *info)
 {
-  TypeNode *node;
-  TypeNode *iface;
-  
+  /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
   g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
   g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
-
-  if (!check_add_interface (instance_type, interface_type))
-    return;
-  node = LOOKUP_TYPE_NODE (instance_type);
-  iface = LOOKUP_TYPE_NODE (interface_type);
-  if (!check_interface_info (iface, NODE_TYPE (node), info))
-    return;
-  type_add_interface (node, iface, info, NULL);
+  
+  G_WRITE_LOCK (&type_rw_lock);
+  if (check_add_interface_L (instance_type, interface_type))
+    {
+      TypeNode *node = lookup_type_node_L (instance_type);
+      TypeNode *iface = lookup_type_node_L (interface_type);
+      
+      if (check_interface_info_L (iface, NODE_TYPE (node), info))
+       type_add_interface_W (node, iface, info, NULL);
+    }
+  G_WRITE_UNLOCK (&type_rw_lock);
 }
 
 void
@@ -1453,18 +1573,25 @@ g_type_add_interface_dynamic (GType        instance_type,
                              GTypePlugin *plugin)
 {
   TypeNode *node;
-  TypeNode *iface;
   
+  /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
   g_return_if_fail (G_TYPE_IS_INSTANTIATABLE (instance_type));
   g_return_if_fail (g_type_parent (interface_type) == G_TYPE_INTERFACE);
-
-  if (!check_add_interface (instance_type, interface_type))
-    return;
-  node = LOOKUP_TYPE_NODE (instance_type);
-  iface = LOOKUP_TYPE_NODE (interface_type);
-  if (!check_plugin (plugin, FALSE, TRUE, NODE_NAME (node)))
+  
+  G_READ_LOCK (&type_rw_lock);
+  node = lookup_type_node_L (instance_type);
+  G_READ_UNLOCK (&type_rw_lock);
+  if (!check_plugin_U (plugin, FALSE, TRUE, NODE_NAME (node)))
     return;
-  type_add_interface (node, iface, NULL, plugin);
+  
+  G_WRITE_LOCK (&type_rw_lock);
+  if (check_add_interface_L (instance_type, interface_type))
+    {
+      TypeNode *iface = lookup_type_node_L (interface_type);
+      
+      type_add_interface_W (node, iface, NULL, plugin);
+    }
+  G_WRITE_UNLOCK (&type_rw_lock);
 }
 
 
@@ -1472,36 +1599,50 @@ g_type_add_interface_dynamic (GType        instance_type,
 gpointer
 g_type_class_ref (GType type)
 {
-  TypeNode *node = LOOKUP_TYPE_NODE (type);
-
+  TypeNode *node;
+  
   /* optimize for common code path
    */
+  G_WRITE_LOCK (&type_rw_lock);
+  node = lookup_type_node_L (type);
   if (node && node->is_classed && node->data &&
       node->data->class.class && node->data->common.ref_count > 0)
     {
-      type_data_ref (node);
-
+      type_data_ref_Wm (node);
+      G_WRITE_UNLOCK (&type_rw_lock);
+      
       return node->data->class.class;
     }
-
+  
   if (!node || !node->is_classed ||
       (node->data && node->data->common.ref_count < 1))
     {
+      G_WRITE_UNLOCK (&type_rw_lock);
       g_warning ("cannot retrive class for invalid (unclassed) type `%s'",
-                type_descriptive_name (type));
+                type_descriptive_name_U (type));
       return NULL;
     }
-
-  type_data_ref (node);
-
+  
+  type_data_ref_Wm (node);
+  
   if (!node->data->class.class)
     {
       GType ptype = NODE_PARENT_TYPE (node);
-      GTypeClass *pclass = ptype ? g_type_class_ref (ptype) : NULL;
-
-      type_class_init (node, pclass);
+      GTypeClass *pclass = NULL;
+      
+      if (ptype)
+       {
+         G_WRITE_UNLOCK (&type_rw_lock);
+         pclass = g_type_class_ref (ptype);
+         if (node->data->class.class)
+            INVALID_RECURSION ("g_type_plugin_*", node->plugin, NODE_NAME (node));
+         G_WRITE_LOCK (&type_rw_lock);
+       }
+      
+      type_class_init_Wm (node, pclass);
     }
-
+  G_WRITE_UNLOCK (&type_rw_lock);
+  
   return node->data->class.class;
 }
 
@@ -1510,16 +1651,18 @@ g_type_class_unref (gpointer g_class)
 {
   TypeNode *node;
   GTypeClass *class = g_class;
-
+  
   g_return_if_fail (g_class != NULL);
-
-  node = LOOKUP_TYPE_NODE (class->g_type);
+  
+  G_WRITE_LOCK (&type_rw_lock);
+  node = lookup_type_node_L (class->g_type);
   if (node && node->is_classed && node->data &&
       node->data->class.class == class && node->data->common.ref_count > 0)
-    type_data_unref (node, FALSE);
+    type_data_unref_Wm (node, FALSE);
   else
     g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
-              type_descriptive_name (class->g_type));
+              type_descriptive_name_L (class->g_type));
+  G_WRITE_UNLOCK (&type_rw_lock);
 }
 
 void
@@ -1527,45 +1670,57 @@ g_type_class_unref_uncached (gpointer g_class)
 {
   TypeNode *node;
   GTypeClass *class = g_class;
-
+  
   g_return_if_fail (g_class != NULL);
-
-  node = LOOKUP_TYPE_NODE (class->g_type);
+  
+  G_WRITE_LOCK (&type_rw_lock);
+  node = lookup_type_node_L (class->g_type);
   if (node && node->is_classed && node->data &&
       node->data->class.class == class && node->data->common.ref_count > 0)
-    type_data_unref (node, TRUE);
+    type_data_unref_Wm (node, TRUE);
   else
     g_warning ("cannot unreference class of invalid (unclassed) type `%s'",
-              type_descriptive_name (class->g_type));
+              type_descriptive_name_L (class->g_type));
+  G_WRITE_UNLOCK (&type_rw_lock);
 }
 
 gpointer
 g_type_class_peek (GType type)
 {
-  TypeNode *node = LOOKUP_TYPE_NODE (type);
-
+  TypeNode *node;
+  gpointer class;
+  
+  G_READ_LOCK (&type_rw_lock);
+  node = lookup_type_node_L (type);
   if (node && node->is_classed && node->data && node->data->class.class) /* common.ref_count _may_ be 0 */
-    return node->data->class.class;
+    class = node->data->class.class;
   else
-    return NULL;
+    class = NULL;
+  G_READ_UNLOCK (&type_rw_lock);
+  
+  return class;
 }
 
 gpointer
 g_type_class_peek_parent (gpointer g_class)
 {
   TypeNode *node;
-
+  gpointer class;
+  
   g_return_val_if_fail (g_class != NULL, NULL);
-
-  node = LOOKUP_TYPE_NODE (G_TYPE_FROM_CLASS (g_class));
+  
+  G_READ_LOCK (&type_rw_lock);
+  node = lookup_type_node_L (G_TYPE_FROM_CLASS (g_class));
   if (node && node->is_classed && node->data && NODE_PARENT_TYPE (node))
     {
-      node = LOOKUP_TYPE_NODE (NODE_PARENT_TYPE (node));
-
-      return node->data->class.class;
+      node = lookup_type_node_L (NODE_PARENT_TYPE (node));
+      class = node->data->class.class;
     }
-
-  return NULL;
+  else
+    class = NULL;
+  G_READ_UNLOCK (&type_rw_lock);
+  
+  return class;
 }
 
 gpointer
@@ -1574,38 +1729,50 @@ g_type_interface_peek (gpointer instance_class,
 {
   TypeNode *node;
   TypeNode *iface;
+  gpointer vtable = NULL;
   GTypeClass *class = instance_class;
-
+  
   g_return_val_if_fail (instance_class != NULL, NULL);
-
-  node = LOOKUP_TYPE_NODE (class->g_type);
-  iface = LOOKUP_TYPE_NODE (iface_type);
+  
+  G_READ_LOCK (&type_rw_lock);
+  node = lookup_type_node_L (class->g_type);
+  iface = lookup_type_node_L (iface_type);
   if (node && node->is_instantiatable && iface)
     {
-      IFaceEntry *entry = type_lookup_iface_entry (node, iface);
-
+      IFaceEntry *entry = type_lookup_iface_entry_L (node, iface);
+      
       if (entry && entry->vtable)
-       return entry->vtable;
+       vtable = entry->vtable;
     }
-
-  return NULL;
+  G_READ_UNLOCK (&type_rw_lock);
+  
+  return vtable;
 }
 
 GTypeValueTable*
 g_type_value_table_peek (GType type)
 {
-  TypeNode *node = LOOKUP_TYPE_NODE (type);
-
-  if (node && node->data && node->data->common.ref_count > 0)
-    return node->data->common.value_table->value_init ? node->data->common.value_table : NULL;
-  else
-    return NULL;
+  TypeNode *node;
+  GTypeValueTable *vtable = NULL;
+  
+  G_READ_LOCK (&type_rw_lock);
+  node = lookup_type_node_L (type);
+  if (node && node->data && node->data->common.ref_count > 0 &&
+      node->data->common.value_table->value_init)
+    vtable = node->data->common.value_table;
+  G_READ_UNLOCK (&type_rw_lock);
+  
+  return vtable;
 }
 
 gchar*
 g_type_name (GType type)
 {
-  TypeNode *node = LOOKUP_TYPE_NODE (type);
+  TypeNode *node;
+  
+  G_READ_LOCK (&type_rw_lock);
+  node = lookup_type_node_L (type);
+  G_READ_UNLOCK (&type_rw_lock);
   
   return node ? NODE_NAME (node) : NULL;
 }
@@ -1613,14 +1780,19 @@ g_type_name (GType type)
 GQuark
 g_type_qname (GType type)
 {
-  TypeNode *node = LOOKUP_TYPE_NODE (type);
-
+  TypeNode *node;
+  
+  G_READ_LOCK (&type_rw_lock);
+  node = lookup_type_node_L (type);
+  G_READ_UNLOCK (&type_rw_lock);
+  
   return node ? node->qname : 0;
 }
 
 GType
 g_type_from_name (const gchar *name)
 {
+  GType type = 0;
   GQuark quark;
   
   g_return_val_if_fail (name != NULL, 0);
@@ -1628,20 +1800,23 @@ g_type_from_name (const gchar *name)
   quark = g_quark_try_string (name);
   if (quark)
     {
-      GType type = GPOINTER_TO_UINT (g_hash_table_lookup (g_type_nodes_ht, GUINT_TO_POINTER (quark)));
-      
-      if (type)
-       return type;
+      G_READ_LOCK (&type_rw_lock);
+      type = GPOINTER_TO_UINT (g_hash_table_lookup (static_type_nodes_ht, GUINT_TO_POINTER (quark)));
+      G_READ_UNLOCK (&type_rw_lock);
     }
   
-  return 0;
+  return type;
 }
 
 GType
 g_type_parent (GType type)
 {
-  TypeNode *node = LOOKUP_TYPE_NODE (type);
-
+  TypeNode *node;
+  
+  G_READ_LOCK (&type_rw_lock);
+  node = lookup_type_node_L (type);
+  G_READ_UNLOCK (&type_rw_lock);
+  
   return node ? NODE_PARENT_TYPE (node) : 0;
 }
 
@@ -1649,89 +1824,80 @@ GType
 g_type_next_base (GType type,
                  GType base_type)
 {
-  TypeNode *node = LOOKUP_TYPE_NODE (type);
+  GType atype = 0;
+  TypeNode *node;
   
+  G_READ_LOCK (&type_rw_lock);
+  node = lookup_type_node_L (type);
   if (node)
     {
-      TypeNode *base_node = LOOKUP_TYPE_NODE (base_type);
+      TypeNode *base_node = lookup_type_node_L (base_type);
       
       if (base_node && base_node->n_supers < node->n_supers)
        {
          guint n = node->n_supers - base_node->n_supers;
          
          if (node->supers[n] == base_type)
-           return node->supers[n - 1];
+           atype = node->supers[n - 1];
        }
     }
+  G_READ_UNLOCK (&type_rw_lock);
   
-  return 0;
-}
-
-#if 0
-gboolean
-g_type_is_a (GType type,
-            GType is_a_type)
-{
-  if (type != is_a_type)
-    {
-      TypeNode *node = LOOKUP_TYPE_NODE (type);
-
-      if (node)
-       {
-         TypeNode *a_node = LOOKUP_TYPE_NODE (is_a_type);
-
-         if (a_node && a_node->n_supers <= node->n_supers)
-           return node->supers[node->n_supers - a_node->n_supers] == is_a_type;
-       }
-    }
-  else
-    return LOOKUP_TYPE_NODE (type) != NULL;
-
-  return FALSE;
+  return atype;
 }
-#endif
 
 gboolean
 g_type_is_a (GType type,
             GType iface_type)
 {
+  gboolean is_a = FALSE;
+  
+  G_READ_LOCK (&type_rw_lock);
   if (type != iface_type)
     {
-      TypeNode *node = LOOKUP_TYPE_NODE (type);
-
+      TypeNode *node = lookup_type_node_L (type);
+      
       if (node)
        {
-         TypeNode *iface_node = LOOKUP_TYPE_NODE (iface_type);
-
+         TypeNode *iface_node = lookup_type_node_L (iface_type);
+         
          if (iface_node)
            {
              if (iface_node->is_iface && node->is_instantiatable)
-               return type_lookup_iface_entry (node, iface_node) != NULL;
+               is_a = type_lookup_iface_entry_L (node, iface_node) != NULL;
              else if (iface_node->n_supers <= node->n_supers)
-               return node->supers[node->n_supers - iface_node->n_supers] == iface_type;
+               is_a = node->supers[node->n_supers - iface_node->n_supers] == iface_type;
            }
        }
     }
   else
-    return LOOKUP_TYPE_NODE (type) != NULL;
-
-  return FALSE;
+    is_a = lookup_type_node_L (type) != NULL;
+  G_READ_UNLOCK (&type_rw_lock);
+  
+  return is_a;
 }
 
 guint
 g_type_fundamental_branch_last (GType type)
 {
   GType ftype = G_TYPE_FUNDAMENTAL (type);
-
-  return ftype < last_fundamental_id ? g_branch_seqnos[ftype] : 0;
+  guint last_type;
+  
+  G_READ_LOCK (&type_rw_lock);
+  last_type = ftype < static_last_fundamental_id ? static_branch_seqnos[ftype] : 0;
+  G_READ_UNLOCK (&type_rw_lock);
+  
+  return last_type;
 }
 
 GType* /* free result */
 g_type_children (GType  type,
                 guint *n_children)
 {
-  TypeNode *node = LOOKUP_TYPE_NODE (type);
+  TypeNode *node;
   
+  G_READ_LOCK (&type_rw_lock);
+  node = lookup_type_node_L (type);
   if (node)
     {
       GType *children = g_new (GType, node->n_children + 1);
@@ -1741,11 +1907,13 @@ g_type_children (GType  type,
       
       if (n_children)
        *n_children = node->n_children;
+      G_READ_UNLOCK (&type_rw_lock);
       
       return children;
     }
   else
     {
+      G_READ_UNLOCK (&type_rw_lock);
       if (n_children)
        *n_children = 0;
       
@@ -1757,27 +1925,31 @@ GType* /* free result */
 g_type_interfaces (GType  type,
                   guint *n_interfaces)
 {
-  TypeNode *node = LOOKUP_TYPE_NODE (type);
-
+  TypeNode *node;
+  
+  G_READ_LOCK (&type_rw_lock);
+  node = lookup_type_node_L (type);
   if (node && node->is_instantiatable)
     {
       GType *ifaces = g_new (GType, node->n_ifaces + 1);
       guint i;
-
+      
       for (i = 0; i < node->n_ifaces; i++)
        ifaces[i] = node->private.iface_entries[i].iface_type;
       ifaces[i] = 0;
-
+      
       if (n_interfaces)
        *n_interfaces = node->n_ifaces;
-
+      G_READ_UNLOCK (&type_rw_lock);
+      
       return ifaces;
     }
   else
     {
+      G_READ_UNLOCK (&type_rw_lock);
       if (n_interfaces)
        *n_interfaces = 0;
-
+      
       return NULL;
     }
 }
@@ -1794,26 +1966,22 @@ struct _QData
   gpointer data;
 };
 
-gpointer
-g_type_get_qdata (GType  type,
-                 GQuark quark)
+static inline gpointer
+type_get_qdata_L (TypeNode *node,
+                 GQuark    quark)
 {
-  TypeNode *node = LOOKUP_TYPE_NODE (type);
-  GData *gdata;
+  GData *gdata = node->global_gdata;
   
-  g_return_val_if_fail (node != NULL, NULL);
-
-  gdata = node->static_gdata;
   if (quark && gdata && gdata->n_qdatas)
     {
       QData *qdatas = gdata->qdatas - 1;
       guint n_qdatas = gdata->n_qdatas;
-
+      
       do
        {
          guint i;
          QData *check;
-
+         
          i = (n_qdatas + 1) / 2;
          check = qdatas + i;
          if (quark == check->quark)
@@ -1828,28 +1996,46 @@ g_type_get_qdata (GType  type,
        }
       while (n_qdatas);
     }
-
   return NULL;
 }
 
-void
-g_type_set_qdata (GType    type,
-                 GQuark   quark,
-                 gpointer data)
+gpointer
+g_type_get_qdata (GType  type,
+                 GQuark quark)
+{
+  TypeNode *node;
+  gpointer data;
+  
+  G_READ_LOCK (&type_rw_lock);
+  node = lookup_type_node_L (type);
+  if (node)
+    {
+      data = type_get_qdata_L (node, quark);
+      G_READ_UNLOCK (&type_rw_lock);
+    }
+  else
+    {
+      G_READ_UNLOCK (&type_rw_lock);
+      g_return_val_if_fail (node != NULL, NULL);
+      data = NULL;
+    }
+  return data;
+}
+
+static inline void
+type_set_qdata_W (TypeNode *node,
+                 GQuark    quark,
+                 gpointer  data)
 {
-  TypeNode *node = LOOKUP_TYPE_NODE (type);
   GData *gdata;
   QData *qdata;
   guint i;
-
-  g_return_if_fail (node != NULL);
-  g_return_if_fail (quark != 0);
-
+  
   /* setup qdata list if necessary */
-  if (!node->static_gdata)
-    node->static_gdata = g_new0 (GData, 1);
-  gdata = node->static_gdata;
-
+  if (!node->global_gdata)
+    node->global_gdata = g_new0 (GData, 1);
+  gdata = node->global_gdata;
+  
   /* try resetting old data */
   qdata = gdata->qdatas;
   for (i = 0; i < gdata->n_qdatas; i++)
@@ -1858,7 +2044,7 @@ g_type_set_qdata (GType    type,
        qdata[i].data = data;
        return;
       }
-
+  
   /* add new entry */
   gdata->n_qdatas++;
   gdata->qdatas = g_renew (QData, gdata->qdatas, gdata->n_qdatas);
@@ -1871,23 +2057,64 @@ g_type_set_qdata (GType    type,
   qdata[i].data = data;
 }
 
+void
+g_type_set_qdata (GType    type,
+                 GQuark   quark,
+                 gpointer data)
+{
+  TypeNode *node;
+  
+  g_return_if_fail (quark != 0);
+  
+  G_WRITE_LOCK (&type_rw_lock);
+  node = lookup_type_node_L (type);
+  if (node)
+    {
+      type_set_qdata_W (node, quark, data);
+      G_WRITE_UNLOCK (&type_rw_lock);
+    }
+  else
+    {
+      G_WRITE_UNLOCK (&type_rw_lock);
+      g_return_if_fail (node != NULL);
+    }
+}
+
+static void
+type_add_flags_W (TypeNode  *node,
+                 GTypeFlags flags)
+{
+  guint dflags;
+  
+  g_return_if_fail ((flags & ~TYPE_FLAG_MASK) == 0);
+  g_return_if_fail (node != NULL);
+  
+  if ((flags & G_TYPE_FLAG_ABSTRACT) && node->is_classed && node->data && node->data->class.class)
+    g_warning ("tagging type `%s' as abstract after class initialization", NODE_NAME (node));
+  dflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags));
+  dflags |= flags;
+  type_set_qdata_W (node, static_quark_type_flags, GUINT_TO_POINTER (dflags));
+}
+
 
 /* --- implementation details --- */
 gboolean
 g_type_check_flags (GType type,
                    guint flags)
 {
-  TypeNode *node = LOOKUP_TYPE_NODE (type);
+  TypeNode *node;
   gboolean result = FALSE;
-
+  
+  G_READ_LOCK (&type_rw_lock);
+  node = lookup_type_node_L (type);
   if (node)
     {
       guint fflags = flags & TYPE_FUNDAMENTAL_FLAG_MASK;
       guint tflags = flags & TYPE_FLAG_MASK;
-
+      
       if (fflags)
        {
-         GTypeFundamentalInfo *finfo = type_node_fundamental_info (node);
+         GTypeFundamentalInfo *finfo = type_node_fundamental_info_L (node);
          
          fflags = (finfo->type_flags & fflags) == fflags;
        }
@@ -1895,20 +2122,26 @@ g_type_check_flags (GType type,
        fflags = TRUE;
       
       if (tflags)
-       tflags = (tflags & GPOINTER_TO_UINT (g_type_get_qdata (type, quark_type_flags))) == tflags;
+       tflags = (tflags & GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags))) == tflags;
       else
        tflags = TRUE;
       
       result = tflags && fflags;
     }
+  G_READ_UNLOCK (&type_rw_lock);
+  
   return result;
 }
 
 GTypePlugin*
 g_type_get_plugin (GType type)
 {
-  TypeNode *node = LOOKUP_TYPE_NODE (type);
-
+  TypeNode *node;
+  
+  G_READ_LOCK (&type_rw_lock);
+  node = lookup_type_node_L (type);
+  G_READ_UNLOCK (&type_rw_lock);
+  
   return node ? node->plugin : NULL;
 }
 
@@ -1916,38 +2149,53 @@ GTypePlugin*
 g_type_interface_get_plugin (GType instance_type,
                             GType interface_type)
 {
-  TypeNode *node = LOOKUP_TYPE_NODE (instance_type);  
-  TypeNode *iface = LOOKUP_TYPE_NODE (interface_type);
-  IFaceHolder *iholder;
-
-  g_return_val_if_fail (node == NULL, NULL);
-  g_return_val_if_fail (iface == NULL, NULL);
-  g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type), NULL);
+  TypeNode *node;
+  TypeNode *iface;
   
-  iholder = iface->private.iface_conformants;
+  g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type), NULL);
   
-  while (iholder && iholder->instance_type != instance_type)
-    iholder = iholder->next;
-
-  if (!iholder)
+  G_READ_LOCK (&type_rw_lock);
+  node = lookup_type_node_L (instance_type);  
+  iface = lookup_type_node_L (interface_type);
+  if (node && iface)
     {
-      g_warning (G_STRLOC ": Attempt to look up plugin for invalid instance/interface type pair.");
-      return NULL;
+      IFaceHolder *iholder = iface->private.iface_conformants;
+      
+      while (iholder && iholder->instance_type != instance_type)
+       iholder = iholder->next;
+      G_READ_UNLOCK (&type_rw_lock);
+      
+      if (iholder)
+       return iholder->plugin;
     }
-
-  return iholder->plugin;
+  else
+    G_READ_UNLOCK (&type_rw_lock);
+  
+  g_return_val_if_fail (node == NULL, NULL);
+  g_return_val_if_fail (iface == NULL, NULL);
+  
+  g_warning (G_STRLOC ": attempt to look up plugin for invalid instance/interface type pair.");
+  
+  return NULL;
 }
 
 GType
 g_type_fundamental_last (void)
 {
-  return last_fundamental_id;
+  GType type;
+  
+  G_READ_LOCK (&type_rw_lock);
+  type = static_last_fundamental_id;
+  G_READ_UNLOCK (&type_rw_lock);
+  
+  return type;
 }
 
 gboolean
 g_type_instance_is_a (GTypeInstance *type_instance,
                      GType          iface_type)
 {
+  /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
   return (type_instance && type_instance->g_class &&
          G_TYPE_IS_INSTANTIATABLE (type_instance->g_class->g_type) &&
          g_type_is_a (type_instance->g_class->g_type, iface_type));
@@ -1957,6 +2205,7 @@ gboolean
 g_type_class_is_a (GTypeClass *type_class,
                   GType       is_a_type)
 {
+  /* G_TYPE_IS_CLASSED() is an external call: _U */
   return (type_class && G_TYPE_IS_CLASSED (type_class->g_type) &&
          g_type_is_a (type_class->g_type, is_a_type));
 }
@@ -1969,17 +2218,23 @@ g_type_value_is_a (GValue *value,
   
   if (!value)
     return FALSE;
-  node = LOOKUP_TYPE_NODE (value->g_type);
+  
+  G_READ_LOCK (&type_rw_lock);
+  node = lookup_type_node_L (value->g_type);
 #if 0
   if (!G_TYPE_IS_FUNDAMENTAL (value->g_type) && !node || !node->data)
-    node = LOOKUP_TYPE_NODE (G_TYPE_FUNDAMENTAL (value->g_type));
+    node = lookup_type_node_L (G_TYPE_FUNDAMENTAL (value->g_type));
 #endif
   if (!node || !node->data || node->data->common.ref_count < 1 ||
-      !node->data->common.value_table->value_init ||
-      !g_type_is_a (value->g_type, type))
-    return FALSE;
+      !node->data->common.value_table->value_init)
+    {
+      G_READ_UNLOCK (&type_rw_lock);
+      
+      return FALSE;
+    }
+  G_READ_UNLOCK (&type_rw_lock);
   
-  return TRUE;
+  return g_type_is_a (value->g_type, type);
 }
 
 gboolean
@@ -1995,30 +2250,31 @@ g_type_check_instance_cast (GTypeInstance *type_instance,
   if (!type_instance)
     {
       g_warning ("invalid cast from (NULL) pointer to `%s'",
-                type_descriptive_name (iface_type));
+                type_descriptive_name_U (iface_type));
       return type_instance;
     }
   if (!type_instance->g_class)
     {
       g_warning ("invalid unclassed pointer in cast to `%s'",
-                type_descriptive_name (iface_type));
+                type_descriptive_name_U (iface_type));
       return type_instance;
     }
+  /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
   if (!G_TYPE_IS_INSTANTIATABLE (type_instance->g_class->g_type))
     {
       g_warning ("invalid uninstantiatable type `%s' in cast to `%s'",
-                type_descriptive_name (type_instance->g_class->g_type),
-                type_descriptive_name (iface_type));
+                type_descriptive_name_U (type_instance->g_class->g_type),
+                type_descriptive_name_U (iface_type));
       return type_instance;
     }
   if (!g_type_is_a (type_instance->g_class->g_type, iface_type))
     {
       g_warning ("invalid cast from `%s' to `%s'",
-                type_descriptive_name (type_instance->g_class->g_type),
-                type_descriptive_name (iface_type));
+                type_descriptive_name_U (type_instance->g_class->g_type),
+                type_descriptive_name_U (iface_type));
       return type_instance;
     }
-
+  
   return type_instance;
 }
 
@@ -2029,24 +2285,25 @@ g_type_check_class_cast (GTypeClass *type_class,
   if (!type_class)
     {
       g_warning ("invalid class cast from (NULL) pointer to `%s'",
-                type_descriptive_name (is_a_type));
+                type_descriptive_name_U (is_a_type));
       return type_class;
     }
+  /* G_TYPE_IS_CLASSED() is an external call: _U */
   if (!G_TYPE_IS_CLASSED (type_class->g_type))
     {
       g_warning ("invalid unclassed type `%s' in class cast to `%s'",
-                type_descriptive_name (type_class->g_type),
-                type_descriptive_name (is_a_type));
+                type_descriptive_name_U (type_class->g_type),
+                type_descriptive_name_U (is_a_type));
       return type_class;
     }
   if (!g_type_is_a (type_class->g_type, is_a_type))
     {
       g_warning ("invalid class cast from `%s' to `%s'",
-                type_descriptive_name (type_class->g_type),
-                type_descriptive_name (is_a_type));
+                type_descriptive_name_U (type_class->g_type),
+                type_descriptive_name_U (is_a_type));
       return type_class;
     }
-
+  
   return type_class;
 }
 
@@ -2066,19 +2323,21 @@ g_type_check_instance (GTypeInstance *type_instance)
       g_warning ("instance with invalid (NULL) class pointer");
       return FALSE;
     }
+  /* G_TYPE_IS_CLASSED() is an external call: _U */
   if (!G_TYPE_IS_CLASSED (type_instance->g_class->g_type))
     {
       g_warning ("instance of invalid unclassed type `%s'",
-                type_descriptive_name (type_instance->g_class->g_type));
+                type_descriptive_name_U (type_instance->g_class->g_type));
       return FALSE;
     }
+  /* G_TYPE_IS_INSTANTIATABLE() is an external call: _U */
   if (!G_TYPE_IS_INSTANTIATABLE (type_instance->g_class->g_type))
     {
       g_warning ("instance of invalid non-instantiatable type `%s'",
-                type_descriptive_name (type_instance->g_class->g_type));
+                type_descriptive_name_U (type_instance->g_class->g_type));
       return FALSE;
     }
-
+  
   return TRUE;
 }
 
@@ -2097,43 +2356,57 @@ extern void     g_signal_init           (void); /* sync with gsignal.c */
 void
 g_type_init (void)
 {
+  G_LOCK_DEFINE_STATIC (type_init_lock);
   static TypeNode *type0_node = NULL;
   GTypeInfo info;
   TypeNode *node;
   GType type;
-
-  if (last_fundamental_id)
-    return;
-
+  
+  G_LOCK (type_init_lock);
+  
+  G_WRITE_LOCK (&type_rw_lock);
+  
+  if (static_last_fundamental_id)
+    {
+      G_WRITE_UNLOCK (&type_rw_lock);
+      G_UNLOCK (type_init_lock);
+      return;
+    }
+  
+  /* quarks */
+  static_quark_type_flags = g_quark_from_static_string ("GTypeFlags");
+  
   /* type qname hash table */
-  g_type_nodes_ht = g_hash_table_new (g_direct_hash, g_direct_equal);
-
+  static_type_nodes_ht = g_hash_table_new (g_direct_hash, g_direct_equal);
+  
   /* invalid type G_TYPE_INVALID (0)
    */
-  last_fundamental_id = 1;
-  g_type_nodes = g_renew (TypeNode**, g_type_nodes, last_fundamental_id);
-  g_type_nodes[0] = &type0_node;
-  g_branch_seqnos = g_renew (GType, g_branch_seqnos, last_fundamental_id);
-  g_branch_seqnos[0] = 1;
-
+  static_last_fundamental_id = 1;
+  static_type_nodes = g_renew (TypeNode**, static_type_nodes, static_last_fundamental_id);
+  static_type_nodes[0] = &type0_node;
+  static_branch_seqnos = g_renew (GType, static_branch_seqnos, static_last_fundamental_id);
+  static_branch_seqnos[0] = 1;
+  
   /* void type G_TYPE_NONE
    */
-  node = type_node_fundamental_new (G_TYPE_NONE, "void", 0);
+  node = type_node_fundamental_new_W (G_TYPE_NONE, "void", 0);
   type = NODE_TYPE (node);
   g_assert (type == G_TYPE_NONE);
-
+  
   /* interface fundamental type G_TYPE_INTERFACE (!classed)
    */
   memset (&info, 0, sizeof (info));
-  node = type_node_fundamental_new (G_TYPE_INTERFACE, "GInterface", G_TYPE_FLAG_DERIVABLE);
+  node = type_node_fundamental_new_W (G_TYPE_INTERFACE, "GInterface", G_TYPE_FLAG_DERIVABLE);
   type = NODE_TYPE (node);
-  type_data_make (node, &info, NULL);
+  type_data_make_W (node, &info, NULL);
   g_assert (type == G_TYPE_INTERFACE);
-
+  
+  G_WRITE_UNLOCK (&type_rw_lock);
+  
   /* G_TYPE_TYPE_PLUGIN
    */
   g_type_plugin_get_type ();
-
+  
   /* G_TYPE_* value types
    */
   g_value_types_init ();
@@ -2145,20 +2418,22 @@ g_type_init (void)
   /* G_TYPE_PARAM
    */
   g_param_type_init ();
-
+  
   /* G_TYPE_PARAM
    */
   g_boxed_type_init ();
-
+  
   /* G_TYPE_OBJECT
    */
   g_object_type_init ();
-
+  
   /* G_TYPE_PARAM_* pspec types
    */
   g_param_spec_types_init ();
-
+  
   /* Signal system
    */
   g_signal_init ();
+  
+  G_UNLOCK (type_init_lock);
 }
index 3fa186f..5e0a182 100644 (file)
@@ -344,6 +344,7 @@ GTypeValueTable* g_type_value_table_peek        (GType                   type);
 #define _G_TYPE_CHV(vl)                        (g_type_check_value ((GValue*) vl))
 #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))
+#define        G_TYPE_FLAG_RESERVED_ID_BIT     (1 << 30)
 
 
 #ifdef __cplusplus
index 466c13d..b7eaded 100644 (file)
  * Boston, MA 02111-1307, USA.
  */
 
+/*
+ * FIXME: MT-safety
+ */
+
 #include <string.h>
 
 #include "gvalue.h"
index 8ead3a5..1980e95 100644 (file)
  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  * Boston, MA 02111-1307, USA.
  */
+
+/*
+ * MT safe
+ */
+
 #include       "gvaluetypes.h"
 
 #include       "gvaluecollector.h"