* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
#include "config.h"
-#include "../glib/valgrind.h"
+#include "../glib/gvalgrind.h"
#include <string.h>
#include "gtype.h"
#include "gatomicarray.h"
#include "gobject_trace.h"
+#include "glib-private.h"
#include "gconstructor.h"
+#ifdef G_OS_WIN32
+#include <windows.h>
+#endif
+
#ifdef G_ENABLE_DEBUG
#define IF_DEBUG(debug_type) if (_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type)
#endif
*
* Type instance and class structs are limited to a total of 64 KiB,
* including all parent types. Similarly, type instances' private data
- * (as created by g_type_class_add_private()) are limited to a total of
+ * (as created by G_ADD_PRIVATE()) are limited to a total of
* 64 KiB. If a type instance needs a large static buffer, allocate it
* separately (typically by using #GArray or #GPtrArray) and put a pointer
* to the buffer in the structure.
*
- * A final word about type names: Such an identifier needs to be at least
- * three characters long. There is no upper length limit. The first character
- * needs to be a letter (a-z or A-Z) or an underscore '_'. Subsequent
- * characters can be letters, numbers or any of '-_+'.
+ * As mentioned in the [GType conventions][gtype-conventions], type names must
+ * be at least three characters long. There is no upper length limit. The first
+ * character must be a letter (a–z or A–Z) or an underscore (‘_’). Subsequent
+ * characters can be letters, numbers or any of ‘-_+’.
*/
#define g_assert_type_system_initialized() \
g_assert (static_quark_type_flags)
-#ifdef G_ENABLE_DEBUG
-#define DEBUG_CODE(debug_type, code_block) G_STMT_START { \
- if (_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type) \
- { code_block; } \
-} G_STMT_END
-#else /* !G_ENABLE_DEBUG */
-#define DEBUG_CODE(debug_type, code_block) /* code_block */
-#endif /* G_ENABLE_DEBUG */
-
#define TYPE_FUNDAMENTAL_FLAG_MASK (G_TYPE_FLAG_CLASSED | \
G_TYPE_FLAG_INSTANTIATABLE | \
G_TYPE_FLAG_DERIVABLE | \
/* --- structures --- */
struct _TypeNode
{
- guint volatile ref_count;
+ guint ref_count; /* (atomic) */
#ifdef G_ENABLE_DEBUG
- guint volatile instance_count;
+ guint instance_count; /* (atomic) */
#endif
GTypePlugin *plugin;
guint n_children; /* writable with lock */
guint is_instantiatable : 1;
guint mutatable_check_cache : 1; /* combines some common path checks */
GType *children; /* writable with lock */
- TypeData * volatile data;
+ TypeData *data;
GQuark qname;
GData *global_gdata;
union {
};
struct _IFaceEntries {
- guint offset_index;
+ gsize offset_index;
IFaceEntry entry[1];
};
CommonData common;
guint16 class_size;
guint16 class_private_size;
- int volatile init_state; /* atomic - g_type_class_ref reads it unlocked */
+ int init_state; /* (atomic) - g_type_class_ref reads it unlocked */
GBaseInitFunc class_init_base;
GBaseFinalizeFunc class_finalize_base;
GClassInitFunc class_init;
CommonData common;
guint16 class_size;
guint16 class_private_size;
- int volatile init_state; /* atomic - g_type_class_ref reads it unlocked */
+ int init_state; /* (atomic) - g_type_class_ref reads it unlocked */
GBaseInitFunc class_init_base;
GBaseFinalizeFunc class_finalize_base;
GClassInitFunc class_init;
static GQuark static_quark_iface_holder = 0;
static GQuark static_quark_dependants_array = 0;
static guint type_registration_serial = 0;
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
GTypeDebugFlags _g_type_debug_flags = 0;
+G_GNUC_END_IGNORE_DEPRECATIONS
/* --- type nodes --- */
static GHashTable *static_type_nodes_ht = NULL;
node = G_STRUCT_MEMBER_P (node, SIZEOF_FUNDAMENTAL_INFO);
static_fundamental_type_nodes[ftype >> G_TYPE_FUNDAMENTAL_SHIFT] = node;
type = ftype;
+
+#if ENABLE_VALGRIND
+ VALGRIND_MALLOCLIKE_BLOCK (node, node_size - SIZEOF_FUNDAMENTAL_INFO, FALSE, TRUE);
+#endif
}
else
type = (GType) node;
}
static inline IFaceEntry*
-lookup_iface_entry_I (volatile IFaceEntries *entries,
- TypeNode *iface_node)
+lookup_iface_entry_I (IFaceEntries *entries,
+ TypeNode *iface_node)
{
guint8 *offsets;
- guint offset_index;
+ gsize offset_index;
IFaceEntry *check;
- int index;
+ gsize index;
IFaceEntry *entry;
if (entries == NULL)
if (entry && entry->vtable == NULL && !type_iface_peek_holder_L (iface, NODE_TYPE (node)))
{
/* ok, we do conform to this interface already, but the interface vtable was not
- * yet intialized, and we just conform to the interface because it got added to
+ * yet initialized, and we just conform to the interface because it got added to
* one of our parents. so we allow overriding of holder info here.
*/
return TRUE;
data->instance.class_private_size = 0;
if (pnode)
data->instance.class_private_size = pnode->data->instance.class_private_size;
-#ifdef DISABLE_MEM_POOLS
- data->instance.n_preallocs = 0;
-#else /* !DISABLE_MEM_POOLS */
data->instance.n_preallocs = MIN (info->n_preallocs, 1024);
-#endif /* !DISABLE_MEM_POOLS */
data->instance.instance_init = info->instance_init;
}
else if (node->is_classed) /* only classed */
static gboolean
iface_node_has_available_offset_L (TypeNode *iface_node,
- int offset,
+ gsize offset,
int for_index)
{
guint8 *offsets;
return FALSE;
}
-static int
+static gsize
find_free_iface_offset_L (IFaceEntries *entries)
{
IFaceEntry *entry;
TypeNode *iface_node;
- int offset;
+ gsize offset;
int i;
int n_entries;
n_entries = IFACE_ENTRIES_N_ENTRIES (entries);
- offset = -1;
+ offset = 0;
do
{
- offset++;
for (i = 0; i < n_entries; i++)
{
entry = &entries->entry[i];
iface_node = lookup_type_node_I (entry->iface_type);
if (!iface_node_has_available_offset_L (iface_node, offset, i))
- break;
+ {
+ offset++;
+ break;
+ }
}
}
while (i != n_entries);
static void
iface_node_set_offset_L (TypeNode *iface_node,
- int offset,
+ gsize offset,
int index)
{
guint8 *offsets, *old_offsets;
- int new_size, old_size;
- int i;
+ gsize new_size, old_size;
+ gsize i;
old_offsets = G_ATOMIC_ARRAY_GET_LOCKED (&iface_node->_prot.offsets, guint8);
if (old_offsets == NULL)
IFaceEntry *entry;
TypeNode *iface_node;
guint i, j;
- int num_entries;
+ guint num_entries;
g_assert (node->is_instantiatable);
if (parent_entry)
{
- if (node->data && node->data->class.init_state >= BASE_IFACE_INIT)
+ if (node->data && g_atomic_int_get (&node->data->class.init_state) >= BASE_IFACE_INIT)
{
entries->entry[i].init_state = INITIALIZED;
entries->entry[i].vtable = parent_entry->vtable;
iholder->next = iface_node_get_holders_L (iface);
iface_node_set_holders_W (iface, iholder);
iholder->instance_type = NODE_TYPE (node);
- iholder->info = info ? g_memdup (info, sizeof (*info)) : NULL;
+ iholder->info = info ? g_memdup2 (info, sizeof (*info)) : NULL;
iholder->plugin = plugin;
/* create an iface entry for this type */
type_node_add_iface_entry_W (node, NODE_TYPE (iface), NULL);
/* if the class is already (partly) initialized, we may need to base
- * initalize and/or initialize the new interface.
+ * initialize and/or initialize the new interface.
*/
if (node->data)
{
- InitState class_state = node->data->class.init_state;
+ InitState class_state = g_atomic_int_get (&node->data->class.init_state);
if (class_state >= BASE_IFACE_INIT)
type_iface_vtable_base_init_Wm (iface, node);
}
}
- for (i = 0; i < prerequisite_node->n_supers + 1; i++)
+ for (i = 0; i < prerequisite_node->n_supers + 1u; i++)
type_iface_add_prerequisite_W (iface, lookup_type_node_I (prerequisite_node->supers[i]));
G_WRITE_UNLOCK (&type_rw_lock);
}
/**
* g_type_interface_prerequisites:
* @interface_type: an interface type
- * @n_prerequisites: (out) (allow-none): location to return the number
+ * @n_prerequisites: (out) (optional): location to return the number
* of prerequisites, or %NULL
*
* Returns the prerequisites of an interfaces type.
}
}
+/**
+ * g_type_interface_instantiatable_prerequisite:
+ * @interface_type: an interface type
+ *
+ * Returns the most specific instantiatable prerequisite of an
+ * interface type. If the interface type has no instantiatable
+ * prerequisite, %G_TYPE_INVALID is returned.
+ *
+ * See g_type_interface_add_prerequisite() for more information
+ * about prerequisites.
+ *
+ * Returns: the instantiatable prerequisite type or %G_TYPE_INVALID if none
+ *
+ * Since: 2.68
+ **/
+GType
+g_type_interface_instantiatable_prerequisite (GType interface_type)
+{
+ TypeNode *inode = NULL;
+ TypeNode *iface;
+ guint i;
+
+ g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type), G_TYPE_INVALID);
+
+ iface = lookup_type_node_I (interface_type);
+ if (iface == NULL)
+ return G_TYPE_INVALID;
+
+ G_READ_LOCK (&type_rw_lock);
+
+ for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
+ {
+ GType prerequisite = IFACE_NODE_PREREQUISITES (iface)[i];
+ TypeNode *node = lookup_type_node_I (prerequisite);
+ if (node->is_instantiatable)
+ {
+ if (!inode || type_node_is_a_L (node, inode))
+ inode = node;
+ }
+ }
+
+ G_READ_UNLOCK (&type_rw_lock);
+
+ if (inode)
+ return NODE_TYPE (inode);
+ else
+ return G_TYPE_INVALID;
+}
static IFaceHolder*
type_iface_peek_holder_L (TypeNode *iface,
INVALID_RECURSION ("g_type_plugin_*", iholder->plugin, NODE_NAME (iface));
check_interface_info_I (iface, instance_type, &tmp_info);
- iholder->info = g_memdup (&tmp_info, sizeof (tmp_info));
+ iholder->info = g_memdup2 (&tmp_info, sizeof (tmp_info));
}
return iholder; /* we don't modify write lock upon returning NULL */
* and structure setups for instances: actual instance creation should
* happen through functions supplied by the type's fundamental type
* implementation. So use of g_type_create_instance() is reserved for
- * implementators of fundamental types only. E.g. instances of the
+ * implementers of fundamental types only. E.g. instances of the
* #GObject hierarchy should be created via g_object_new() and never
* directly through g_type_create_instance() which doesn't handle things
* like singleton objects or object construction.
private_size = node->data->instance.private_size;
ivar_size = node->data->instance.instance_size;
+#ifdef ENABLE_VALGRIND
if (private_size && RUNNING_ON_VALGRIND)
{
private_size += ALIGN_STRUCT (1);
VALGRIND_MALLOCLIKE_BLOCK (allocated + ALIGN_STRUCT (1), private_size - ALIGN_STRUCT (1), 0, TRUE);
}
else
+#endif
allocated = g_slice_alloc0 (private_size + ivar_size);
instance = (GTypeInstance *) (allocated + private_size);
memset (allocated, 0xaa, ivar_size + private_size);
#endif
+#ifdef ENABLE_VALGRIND
/* See comment in g_type_create_instance() about what's going on here.
* We're basically unwinding what we put into motion there.
*/
VALGRIND_FREELIKE_BLOCK (instance, 0);
}
else
+#endif
g_slice_free1 (private_size + ivar_size, allocated);
#ifdef G_ENABLE_DEBUG
IFaceEntry *pentry = type_lookup_iface_entry_L (pnode, iface);
if (pentry)
- vtable = g_memdup (pentry->vtable, iface->data->iface.vtable_size);
+ vtable = g_memdup2 (pentry->vtable, iface->data->iface.vtable_size);
}
if (!vtable)
- vtable = g_memdup (iface->data->iface.dflt_vtable, iface->data->iface.vtable_size);
+ vtable = g_memdup2 (iface->data->iface.dflt_vtable, iface->data->iface.vtable_size);
entry->vtable = vtable;
vtable->g_type = NODE_TYPE (iface);
vtable->g_instance_type = NODE_TYPE (node);
TypeNode *bnode, *pnode;
guint i;
- /* Accessing data->class will work for instantiable types
+ /* Accessing data->class will work for instantiatable types
* too because ClassData is a subset of InstanceData
*/
g_assert (node->is_classed && node->data &&
node->data->class.class_size &&
!node->data->class.class &&
- node->data->class.init_state == UNINITIALIZED);
+ g_atomic_int_get (&node->data->class.init_state) == UNINITIALIZED);
if (node->data->class.class_private_size)
class = g_malloc0 (ALIGN_STRUCT (node->data->class.class_size) + node->data->class.class_private_size);
else
* inherited interfaces are already init_state == INITIALIZED, because
* they either got setup in the above base_init loop, or during
* class_init from within type_add_interface_Wm() for this or
- * an anchestor type.
+ * an ancestor type.
*/
i = 0;
while ((entries = CLASSED_NODE_IFACES_ENTRIES_LOCKED (node)) != NULL)
/**
* g_type_add_interface_static:
- * @instance_type: #GType value of an instantiable type
+ * @instance_type: #GType value of an instantiatable type
* @interface_type: #GType value of an interface type
* @info: #GInterfaceInfo structure for this
* (@instance_type, @interface_type) combination
*
- * Adds the static @interface_type to @instantiable_type.
+ * Adds @interface_type to the static @instance_type.
* The information contained in the #GInterfaceInfo structure
* pointed to by @info is used to manage the relationship.
*/
/**
* g_type_add_interface_dynamic:
- * @instance_type: #GType value of an instantiable type
+ * @instance_type: #GType value of an instantiatable type
* @interface_type: #GType value of an interface type
* @plugin: #GTypePlugin structure to retrieve the #GInterfaceInfo from
*
- * Adds the dynamic @interface_type to @instantiable_type. The information
+ * Adds @interface_type to the dynamic @instance_type. The information
* contained in the #GTypePlugin structure pointed to by @plugin
* is used to manage the relationship.
*/
* and returns the default interface vtable for the type.
*
* If the type is not currently in use, then the default vtable
- * for the type will be created and initalized by calling
+ * for the type will be created and initialized by calling
* the base interface init and default vtable init functions for
* the type (the @base_init and @class_init members of #GTypeInfo).
* Calling g_type_default_interface_ref() is useful when you
/**
* g_type_default_interface_unref:
* @g_iface: (type GObject.TypeInterface): the default vtable
- * structure for a interface, as returned by g_type_default_interface_ref()
+ * structure for an interface, as returned by g_type_default_interface_ref()
*
* Decrements the reference count for the type corresponding to the
* interface default vtable @g_iface. If the type is dynamic, then
/**
* g_type_from_name:
- * @name: type name to lookup
+ * @name: type name to look up
*
- * Lookup the type ID from a given type name, returning 0 if no type
+ * Look up the type ID from a given type name, returning 0 if no type
* has been registered under this name (this is the preferred method
* to find out by name whether a specific type has been registered
* yet).
* @root_type: immediate parent of the returned type
*
* Given a @leaf_type and a @root_type which is contained in its
- * anchestry, return the type that @root_type is the immediate parent
+ * ancestry, return the type that @root_type is the immediate parent
* of. In other words, this function determines the type that is
* derived directly from @root_type which is also a base class of
* @leaf_type. Given a root type and a leaf type, this function can
* be used to determine the types and order in which the leaf type is
* descended from the root type.
*
- * Returns: immediate child of @root_type and anchestor of @leaf_type
+ * Returns: immediate child of @root_type and ancestor of @leaf_type
*/
GType
g_type_next_base (GType type,
/**
* g_type_is_a:
- * @type: type to check anchestry for
- * @is_a_type: possible anchestor of @type or interface that @type
+ * @type: type to check ancestry for
+ * @is_a_type: possible ancestor of @type or interface that @type
* could conform to
*
* If @is_a_type is a derivable type, check whether @type is a
/**
* g_type_children:
* @type: the parent type
- * @n_children: (out) (allow-none): location to store the length of
+ * @n_children: (out) (optional): location to store the length of
* the returned array, or %NULL
*
* Return a newly allocated and 0-terminated array of type IDs, listing
G_READ_LOCK (&type_rw_lock); /* ->children is relocatable */
children = g_new (GType, node->n_children + 1);
- memcpy (children, node->children, sizeof (GType) * node->n_children);
+ if (node->n_children != 0)
+ memcpy (children, node->children, sizeof (GType) * node->n_children);
children[node->n_children] = 0;
if (n_children)
/**
* g_type_interfaces:
* @type: the type to list interface types for
- * @n_interfaces: (out) (allow-none): location to store the length of
+ * @n_interfaces: (out) (optional): location to store the length of
* the returned array, or %NULL
*
* Return a newly allocated and 0-terminated array of type IDs, listing
}
gboolean
-g_type_check_value (GValue *value)
+g_type_check_value (const GValue *value)
{
return value && type_check_is_value_type_U (value->g_type);
}
gboolean
-g_type_check_value_holds (GValue *value,
- GType type)
+g_type_check_value_holds (const GValue *value,
+ GType type)
{
return value && type_check_is_value_type_U (value->g_type) && g_type_is_a (value->g_type, type);
}
*
* Deprecated: 2.36: the type system is now initialised automatically
*/
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
void
g_type_init_with_debug_flags (GTypeDebugFlags debug_flags)
{
if (debug_flags)
g_message ("g_type_init_with_debug_flags() is no longer supported. Use the GOBJECT_DEBUG environment variable.");
}
+G_GNUC_END_IGNORE_DEPRECATIONS
/**
* g_type_init:
g_assert_type_system_initialized ();
}
-#if defined (G_HAS_CONSTRUCTORS)
-#ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
-#pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(gobject_init_ctor)
-#endif
-G_DEFINE_CONSTRUCTOR(gobject_init_ctor)
-#else
-# error Your platform/compiler is missing constructor support
-#endif
-
static void
-gobject_init_ctor (void)
+gobject_init (void)
{
const gchar *env_string;
GTypeInfo info;
TypeNode *node;
- GType type;
+ GType type G_GNUC_UNUSED /* when compiling with G_DISABLE_ASSERT */;
+
+ /* Ensure GLib is initialized first, see
+ * https://bugzilla.gnome.org/show_bug.cgi?id=756139
+ */
+ GLIB_PRIVATE_CALL (glib_init) ();
G_WRITE_LOCK (&type_rw_lock);
_g_type_debug_flags = g_parse_debug_string (env_string, debug_keys, G_N_ELEMENTS (debug_keys));
}
-
+
/* quarks */
static_quark_type_flags = g_quark_from_static_string ("-g-type-private--GTypeFlags");
static_quark_iface_holder = g_quark_from_static_string ("-g-type-private--IFaceHolder");
static_quark_dependants_array = g_quark_from_static_string ("-g-type-private--dependants-array");
-
+
/* type qname hash table */
static_type_nodes_ht = g_hash_table_new (g_str_hash, g_str_equal);
-
+
/* invalid type G_TYPE_INVALID (0)
*/
static_fundamental_type_nodes[0] = NULL;
-
+
/* void type G_TYPE_NONE
*/
node = type_node_fundamental_new_W (G_TYPE_NONE, g_intern_static_string ("void"), 0);
type = NODE_TYPE (node);
g_assert (type == G_TYPE_NONE);
-
+
/* interface fundamental type G_TYPE_INTERFACE (!classed)
*/
memset (&info, 0, sizeof (info));
type = NODE_TYPE (node);
type_data_make_W (node, &info, NULL);
g_assert (type == G_TYPE_INTERFACE);
-
+
G_WRITE_UNLOCK (&type_rw_lock);
-
+
_g_value_c_init ();
/* G_TYPE_TYPE_PLUGIN
*/
g_type_ensure (g_type_plugin_get_type ());
-
+
/* G_TYPE_* value types
*/
_g_value_types_init ();
-
+
/* G_TYPE_ENUM & G_TYPE_FLAGS
*/
_g_enum_types_init ();
-
+
/* G_TYPE_BOXED
*/
_g_boxed_type_init ();
-
+
/* G_TYPE_PARAM
*/
_g_param_type_init ();
-
+
/* G_TYPE_OBJECT
*/
_g_object_type_init ();
-
+
/* G_TYPE_PARAM_* pspec types
*/
_g_param_spec_types_init ();
-
+
/* Value Transformations
*/
_g_value_transforms_init ();
-
+
/* Signal system
*/
_g_signal_init ();
}
+#if defined (G_OS_WIN32)
+
+BOOL WINAPI DllMain (HINSTANCE hinstDLL,
+ DWORD fdwReason,
+ LPVOID lpvReserved);
+
+BOOL WINAPI
+DllMain (HINSTANCE hinstDLL,
+ DWORD fdwReason,
+ LPVOID lpvReserved)
+{
+ switch (fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ gobject_init ();
+ break;
+
+ default:
+ /* do nothing */
+ ;
+ }
+
+ return TRUE;
+}
+
+#elif defined (G_HAS_CONSTRUCTORS)
+#ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
+#pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(gobject_init_ctor)
+#endif
+G_DEFINE_CONSTRUCTOR(gobject_init_ctor)
+
+static void
+gobject_init_ctor (void)
+{
+ gobject_init ();
+}
+
+#else
+# error Your platform/compiler is missing constructor support
+#endif
+
/**
* g_type_class_add_private:
- * @g_class: class structure for an instantiatable type
+ * @g_class: (type GObject.TypeClass): class structure for an instantiatable
+ * type
* @private_size: size of private structure
*
* Registers a private structure for an instantiatable type.
* ]|
*
* Since: 2.4
+ * Deprecated: 2.58: Use the G_ADD_PRIVATE() macro with the `G_DEFINE_*`
+ * family of macros to add instance private data to a type
*/
void
g_type_class_add_private (gpointer g_class,
/**
* g_type_class_get_instance_private_offset: (skip)
- * @g_class: a #GTypeClass
+ * @g_class: (type GObject.TypeClass): a #GTypeClass
*
* Gets the offset of the private data for instances of @g_class.
*
/**
* g_type_add_class_private:
- * @class_type: GType of an classed type
+ * @class_type: GType of a classed type
* @private_size: size of private structure
*
* Registers a private class structure for a classed type;
if (G_UNLIKELY (type == (GType)-1))
g_error ("can't happen");
}
-