From f0b9abe801c2e0cccb7930421a81bb77031e3251 Mon Sep 17 00:00:00 2001 From: Tim Janik Date: Wed, 31 Jan 2001 06:27:41 +0000 Subject: [PATCH] adapt to work with new CVS gtk-doc, leaving the old rules in place caused Wed Jan 31 07:14:22 2001 Tim Janik * 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 * gobject/tmpl/types.sgml: applied docu patch from Eric Lemings , did some more editing. Wed Jan 31 06:19:49 2001 Tim Janik * 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. --- docs/reference/ChangeLog | 27 +- docs/reference/glib/Makefile.am | 29 +- docs/reference/gobject/Makefile.am | 29 +- docs/reference/gobject/gobject-sections.txt | 25 +- docs/reference/gobject/tmpl/closures.sgml | 92 +- docs/reference/gobject/tmpl/param_specs.sgml | 55 +- docs/reference/gobject/tmpl/types.sgml | 107 +- docs/reference/gobject/tmpl/value_types.sgml | 9 + gobject/ChangeLog | 13 + gobject/gclosure.c | 1 + gobject/genums.c | 4 + gobject/gobject.c | 18 +- gobject/gparam.c | 165 ++- gobject/gparam.h | 8 +- gobject/gparamspecs.c | 5 + gobject/gsignal.c | 30 +- gobject/gtype.c | 1401 +++++++++++------- gobject/gtype.h | 1 + gobject/gvalue.c | 4 + gobject/gvaluetypes.c | 5 + 20 files changed, 1291 insertions(+), 737 deletions(-) diff --git a/docs/reference/ChangeLog b/docs/reference/ChangeLog index a7f1e447f..a3858899e 100644 --- a/docs/reference/ChangeLog +++ b/docs/reference/ChangeLog @@ -1,7 +1,32 @@ +Wed Jan 31 07:14:22 2001 Tim Janik + + * 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 + + * gobject/tmpl/types.sgml: applied docu patch from Eric Lemings + , did some more editing. + 2001-01-30 Sebastian Wilhelmi * 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 diff --git a/docs/reference/glib/Makefile.am b/docs/reference/glib/Makefile.am index a683112f1..72d66c5b9 100644 --- a/docs/reference/glib/Makefile.am +++ b/docs/reference/glib/Makefile.am @@ -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) diff --git a/docs/reference/gobject/Makefile.am b/docs/reference/gobject/Makefile.am index 855cb567d..d25699782 100644 --- a/docs/reference/gobject/Makefile.am +++ b/docs/reference/gobject/Makefile.am @@ -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) diff --git a/docs/reference/gobject/gobject-sections.txt b/docs/reference/gobject/gobject-sections.txt index 80e6c1391..5c3106882 100644 --- a/docs/reference/gobject/gobject-sections.txt +++ b/docs/reference/gobject/gobject-sections.txt @@ -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 @@ -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
@@ -462,18 +469,20 @@ g_signal_type_cclosure_new
Closures closures -GClosureMarshal -GClosureNotify -GClosure -GCClosure -GClosureNotifyData -GCallback G_CLOSURE_NEEDS_MARSHAL G_CCLOSURE_SWAP_DATA +G_CALLBACK +GCallback +GClosure +GCClosure +GClosureMarshal +GClosureNotify +GClosureNotifyData 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 diff --git a/docs/reference/gobject/tmpl/closures.sgml b/docs/reference/gobject/tmpl/closures.sgml index 8a0435d05..1fc7fb748 100644 --- a/docs/reference/gobject/tmpl/closures.sgml +++ b/docs/reference/gobject/tmpl/closures.sgml @@ -14,6 +14,51 @@ Closures + + + + + +@closure: + + + + + + + +@cclosure: + + + + + + + +@f: + + + + + + + + + + + + + +@is_invalid: + + + + + + +@closure: +@callback: + @@ -36,21 +81,6 @@ Closures @closure: - - - - - -@is_invalid: - - - - - - -@closure: -@callback: - @@ -59,28 +89,6 @@ Closures @data: @notify: - - - - - - - - - - - -@closure: - - - - - - - -@cclosure: - - @@ -123,6 +131,16 @@ Closures @Returns: + + + + + +@sizeof_closure: +@object: +@Returns: + + diff --git a/docs/reference/gobject/tmpl/param_specs.sgml b/docs/reference/gobject/tmpl/param_specs.sgml index 3ba886965..53319627a 100644 --- a/docs/reference/gobject/tmpl/param_specs.sgml +++ b/docs/reference/gobject/tmpl/param_specs.sgml @@ -88,6 +88,27 @@ Parameter Specifications @type: + + + + + + + + + + + + + + + + + + + + + @@ -205,19 +226,36 @@ Parameter Specifications @Returns: - + + + + + +@instance_size: +@n_preallocs: +@instance_init: +@value_type: +@finalize: +@value_set_default: +@value_validate: +@values_cmp: + + -@param_type: @name: -@nick: -@blurb: -@flags: +@pspec_info: @Returns: + + + + + + @@ -259,13 +297,16 @@ Parameter Specifications @Returns: - + +@param_type: @name: -@pspec_info: +@nick: +@blurb: +@flags: @Returns: diff --git a/docs/reference/gobject/tmpl/types.sgml b/docs/reference/gobject/tmpl/types.sgml index 5adeac832..3994dd5a4 100644 --- a/docs/reference/gobject/tmpl/types.sgml +++ b/docs/reference/gobject/tmpl/types.sgml @@ -2,11 +2,26 @@ GType - +The GLib Runtime type identification and management system - +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. + + +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. @@ -16,21 +31,25 @@ GType - +A numerical value which represents the unique identifier of a registered +type. - +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. -@type: +@type: a #GType value - +An integer constant that represents the number of identifiers reserved +for types that are assigned at compile-time. @@ -54,25 +73,32 @@ GType - +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 +rarely needed feature). - +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. -@type: +@type: A #GType value. - +Returns #TRUE if @type is derived (or in object-oriented terminolgy: +inherited) from another type (this holds true for all non-fundamental +types). -@type: +@type: A #GType value. @@ -80,7 +106,7 @@ GType -@type: +@type: A #GType value. @@ -88,7 +114,7 @@ GType -@type: +@type: A #GType value. @@ -96,15 +122,16 @@ GType -@type: +@type: A #GType value. - +Returns #TRUE if @type can be instantiated. Instantiation is the +process of creating an instance (object) of this type. -@type: +@type: A #GType value. @@ -112,7 +139,7 @@ GType -@type: +@type: A #GType value. @@ -120,15 +147,18 @@ GType -@type: +@type: A #GType value. - +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). -@type: +@type: A #GType value. @@ -195,19 +225,27 @@ GType - +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(). -@class_size: -@base_init: -@base_finalize: -@class_init: -@class_finalize: -@class_data: -@instance_size: -@n_preallocs: -@instance_init: -@value_table: +@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). @@ -346,6 +384,13 @@ GType @g_type: + + + + + + + Prior to any use of the type system, g_type_init() has to be called to initialize diff --git a/docs/reference/gobject/tmpl/value_types.sgml b/docs/reference/gobject/tmpl/value_types.sgml index b7907b33b..9e568b26e 100644 --- a/docs/reference/gobject/tmpl/value_types.sgml +++ b/docs/reference/gobject/tmpl/value_types.sgml @@ -371,6 +371,15 @@ Standard value types @v_pointer: + + + + + +@value: +@Returns: + + diff --git a/gobject/ChangeLog b/gobject/ChangeLog index 8a1d14cbb..979ba2cc6 100644 --- a/gobject/ChangeLog +++ b/gobject/ChangeLog @@ -1,3 +1,16 @@ +Wed Jan 31 06:19:49 2001 Tim Janik + + * 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 * makefile.msc.in: Don't try to compile gmarshal.c on its own. diff --git a/gobject/gclosure.c b/gobject/gclosure.c index d99b71887..d303f2b44 100644 --- a/gobject/gclosure.c +++ b/gobject/gclosure.c @@ -16,6 +16,7 @@ * Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307, USA. */ + #include "gclosure.h" #include "gvalue.h" diff --git a/gobject/genums.c b/gobject/genums.c index e60ec2048..4ef62d021 100644 --- a/gobject/genums.c +++ b/gobject/genums.c @@ -17,6 +17,10 @@ * Boston, MA 02111-1307, USA. */ +/* + * MT safe + */ + #include #include "genums.h" diff --git a/gobject/gobject.c b/gobject/gobject.c index f4b82338f..916996da7 100644 --- a/gobject/gobject.c +++ b/gobject/gobject.c @@ -16,6 +16,11 @@ * 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 */ } diff --git a/gobject/gparam.c b/gobject/gparam.c index 3e6b52c99..0c99722f8 100644 --- a/gobject/gparam.c +++ b/gobject/gparam.c @@ -16,6 +16,11 @@ * Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307, USA. */ + +/* + * MT safe + */ + #include "gparam.h" @@ -25,8 +30,11 @@ /* --- 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; } diff --git a/gobject/gparam.h b/gobject/gparam.h index bf8a16cc8..3a27b1ff8 100644 --- a/gobject/gparam.h +++ b/gobject/gparam.h @@ -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 --- */ diff --git a/gobject/gparamspecs.c b/gobject/gparamspecs.c index e42a832dd..cc40f736b 100644 --- a/gobject/gparamspecs.c +++ b/gobject/gparamspecs.c @@ -16,6 +16,11 @@ * Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307, USA. */ + +/* + * MT safe + */ + #include "gparamspecs.h" #include "gvaluecollector.h" diff --git a/gobject/gsignal.c b/gobject/gsignal.c index 16f464bf5..c251670d9 100644 --- a/gobject/gsignal.c +++ b/gobject/gsignal.c @@ -19,11 +19,15 @@ * this code is based on the original GtkSignal implementation * for the Gtk+ library by Peter Mattis */ -#include + +/* + * MT safe + */ #include "gsignal.h" #include "gbsearcharray.h" #include "gvaluecollector.h" +#include /* 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" diff --git a/gobject/gtype.c b/gobject/gtype.c index 6aba911f9..6aaa94b09 100644 --- a/gobject/gtype.c +++ b/gobject/gtype.c @@ -36,9 +36,40 @@ * * 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 : ""; + TypeNode *node = lookup_type_node_L (type); + + return node ? NODE_NAME (node) : ""; } else return ""; } +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,13 +1450,6 @@ g_type_register_fundamental (GType type_id, type_id); return 0; } - if (LOOKUP_TYPE_NODE (type_id)) - { - g_warning ("cannot register existing fundamental type `%s' (as `%s')", - type_descriptive_name (type_id), - type_name); - return 0; - } if ((finfo->type_flags & G_TYPE_FLAG_INSTANTIATABLE) && !(finfo->type_flags & G_TYPE_FLAG_CLASSED)) { @@ -1347,16 +1457,25 @@ g_type_register_fundamental (GType 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); - + G_WRITE_LOCK (&type_rw_lock); + if (lookup_type_node_L (type_id)) + { + 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_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)) + + if (!check_type_name_U (type_name) || + !check_derivation_U (parent_type, type_name) || + !check_plugin_U (plugin, TRUE, FALSE, type_name)) return 0; - if (!check_derivation (parent_type, type_name)) - return 0; - if (!check_plugin (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)) + + 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; - node = LOOKUP_TYPE_NODE (instance_type); - iface = LOOKUP_TYPE_NODE (interface_type); - if (!check_plugin (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; + return atype; } -#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; -} -#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); + TypeNode *node; + TypeNode *iface; + g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type), NULL); - iholder = iface->private.iface_conformants; - - 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); } diff --git a/gobject/gtype.h b/gobject/gtype.h index 3fa186ffb..5e0a18283 100644 --- a/gobject/gtype.h +++ b/gobject/gtype.h @@ -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 diff --git a/gobject/gvalue.c b/gobject/gvalue.c index 466c13d56..b7eaded96 100644 --- a/gobject/gvalue.c +++ b/gobject/gvalue.c @@ -17,6 +17,10 @@ * Boston, MA 02111-1307, USA. */ +/* + * FIXME: MT-safety + */ + #include #include "gvalue.h" diff --git a/gobject/gvaluetypes.c b/gobject/gvaluetypes.c index 8ead3a51c..1980e9537 100644 --- a/gobject/gvaluetypes.c +++ b/gobject/gvaluetypes.c @@ -16,6 +16,11 @@ * Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307, USA. */ + +/* + * MT safe + */ + #include "gvaluetypes.h" #include "gvaluecollector.h"