mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-03-31 12:53:07 +02:00
gobject: simplify object-in-construction handling
Rather than keeping a global list of objects that are being constructed, use qdata on the object itself like we do with several other properties now. https://bugzilla.gnome.org/show_bug.cgi?id=661576
This commit is contained in:
parent
0d62eb467f
commit
efecfe0fac
@ -197,11 +197,10 @@ static GQuark quark_closure_array = 0;
|
|||||||
static GQuark quark_weak_refs = 0;
|
static GQuark quark_weak_refs = 0;
|
||||||
static GQuark quark_toggle_refs = 0;
|
static GQuark quark_toggle_refs = 0;
|
||||||
static GQuark quark_notify_queue;
|
static GQuark quark_notify_queue;
|
||||||
|
static GQuark quark_in_construction;
|
||||||
static GParamSpecPool *pspec_pool = NULL;
|
static GParamSpecPool *pspec_pool = NULL;
|
||||||
static gulong gobject_signals[LAST_SIGNAL] = { 0, };
|
static gulong gobject_signals[LAST_SIGNAL] = { 0, };
|
||||||
static guint (*floating_flag_handler) (GObject*, gint) = object_floating_flag_handler;
|
static guint (*floating_flag_handler) (GObject*, gint) = object_floating_flag_handler;
|
||||||
G_LOCK_DEFINE_STATIC (construction_mutex);
|
|
||||||
static GSList *construction_objects = NULL;
|
|
||||||
/* qdata pointing to GSList<GWeakRef *>, protected by weak_locations_lock */
|
/* qdata pointing to GSList<GWeakRef *>, protected by weak_locations_lock */
|
||||||
static GQuark quark_weak_locations = 0;
|
static GQuark quark_weak_locations = 0;
|
||||||
static GRWLock weak_locations_lock;
|
static GRWLock weak_locations_lock;
|
||||||
@ -451,6 +450,7 @@ g_object_do_class_init (GObjectClass *class)
|
|||||||
quark_weak_locations = g_quark_from_static_string ("GObject-weak-locations");
|
quark_weak_locations = g_quark_from_static_string ("GObject-weak-locations");
|
||||||
quark_toggle_refs = g_quark_from_static_string ("GObject-toggle-references");
|
quark_toggle_refs = g_quark_from_static_string ("GObject-toggle-references");
|
||||||
quark_notify_queue = g_quark_from_static_string ("GObject-notify-queue");
|
quark_notify_queue = g_quark_from_static_string ("GObject-notify-queue");
|
||||||
|
quark_in_construction = g_quark_from_static_string ("GObject-in-construction");
|
||||||
pspec_pool = g_param_spec_pool_new (TRUE);
|
pspec_pool = g_param_spec_pool_new (TRUE);
|
||||||
|
|
||||||
class->constructor = g_object_constructor;
|
class->constructor = g_object_constructor;
|
||||||
@ -951,13 +951,9 @@ g_object_interface_list_properties (gpointer g_iface,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline gboolean
|
static inline gboolean
|
||||||
object_in_construction_list (GObject *object)
|
object_in_construction (GObject *object)
|
||||||
{
|
{
|
||||||
gboolean in_construction;
|
return g_datalist_id_get_data (&object->qdata, quark_in_construction) != NULL;
|
||||||
G_LOCK (construction_mutex);
|
|
||||||
in_construction = g_slist_find (construction_objects, object) != NULL;
|
|
||||||
G_UNLOCK (construction_mutex);
|
|
||||||
return in_construction;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -975,10 +971,8 @@ g_object_init (GObject *object,
|
|||||||
|
|
||||||
if (CLASS_HAS_CUSTOM_CONSTRUCTOR (class))
|
if (CLASS_HAS_CUSTOM_CONSTRUCTOR (class))
|
||||||
{
|
{
|
||||||
/* enter construction list for notify_queue_thaw() and to allow construct-only properties */
|
/* mark object in-construction for notify_queue_thaw() and to allow construct-only properties */
|
||||||
G_LOCK (construction_mutex);
|
g_datalist_id_set_data (&object->qdata, quark_in_construction, object);
|
||||||
construction_objects = g_slist_prepend (construction_objects, object);
|
|
||||||
G_UNLOCK (construction_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef G_ENABLE_DEBUG
|
#ifdef G_ENABLE_DEBUG
|
||||||
@ -1031,7 +1025,7 @@ g_object_real_dispose (GObject *object)
|
|||||||
static void
|
static void
|
||||||
g_object_finalize (GObject *object)
|
g_object_finalize (GObject *object)
|
||||||
{
|
{
|
||||||
if (object_in_construction_list (object))
|
if (object_in_construction (object))
|
||||||
{
|
{
|
||||||
g_error ("object %s %p finalized while still in-construction",
|
g_error ("object %s %p finalized while still in-construction",
|
||||||
G_OBJECT_TYPE_NAME (object), object);
|
G_OBJECT_TYPE_NAME (object), object);
|
||||||
@ -1578,28 +1572,6 @@ g_object_new (GType object_type,
|
|||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
slist_maybe_remove (GSList **slist,
|
|
||||||
gconstpointer data)
|
|
||||||
{
|
|
||||||
GSList *last = NULL, *node = *slist;
|
|
||||||
while (node)
|
|
||||||
{
|
|
||||||
if (node->data == data)
|
|
||||||
{
|
|
||||||
if (last)
|
|
||||||
last->next = node->next;
|
|
||||||
else
|
|
||||||
*slist = node->next;
|
|
||||||
g_slist_free_1 (node);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
last = node;
|
|
||||||
node = last->next;
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gpointer
|
static gpointer
|
||||||
g_object_new_with_custom_constructor (GObjectClass *class,
|
g_object_new_with_custom_constructor (GObjectClass *class,
|
||||||
GObjectConstructParam *params,
|
GObjectConstructParam *params,
|
||||||
@ -1676,25 +1648,23 @@ g_object_new_with_custom_constructor (GObjectClass *class,
|
|||||||
g_free (cvalues);
|
g_free (cvalues);
|
||||||
|
|
||||||
/* There is code in the wild that relies on being able to return NULL
|
/* There is code in the wild that relies on being able to return NULL
|
||||||
* from its custom constructor. This was never a supported operation
|
* from its custom constructor. This was never a supported operation,
|
||||||
* and will leak memory, but since the code is already out there...
|
* but since the code is already out there...
|
||||||
*/
|
*/
|
||||||
if (object == NULL)
|
if (object == NULL)
|
||||||
{
|
{
|
||||||
g_critical ("Custom constructor for class %s returned NULL (which is invalid). Unable to remove object "
|
g_critical ("Custom constructor for class %s returned NULL (which is invalid). "
|
||||||
"from construction_objects list, so memory was probably just leaked. Please use GInitable "
|
"Please use GInitable instead.", G_OBJECT_CLASS_NAME (class));
|
||||||
"instead.", G_OBJECT_CLASS_NAME (class));
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* g_object_init() will have added us to the construction_objects
|
/* g_object_init() will have marked the object as being in-construction.
|
||||||
* list. Check if we're in it (and remove us) in order to find
|
* Check if the returned object still is so marked, or if this is an
|
||||||
* out if we were newly-constructed or this is an already-existing
|
* already-existing singleton (in which case we should not do 'constructed').
|
||||||
* singleton (in which case we should not do 'constructed').
|
|
||||||
*/
|
*/
|
||||||
G_LOCK (construction_mutex);
|
newly_constructed = object_in_construction (object);
|
||||||
newly_constructed = slist_maybe_remove (&construction_objects, object);
|
if (newly_constructed)
|
||||||
G_UNLOCK (construction_mutex);
|
g_datalist_id_set_data (&object->qdata, quark_in_construction, NULL);
|
||||||
|
|
||||||
if (CLASS_HAS_PROPS (class))
|
if (CLASS_HAS_PROPS (class))
|
||||||
{
|
{
|
||||||
@ -2112,7 +2082,7 @@ g_object_set_valist (GObject *object,
|
|||||||
G_OBJECT_TYPE_NAME (object));
|
G_OBJECT_TYPE_NAME (object));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ((pspec->flags & G_PARAM_CONSTRUCT_ONLY) && !object_in_construction_list (object))
|
if ((pspec->flags & G_PARAM_CONSTRUCT_ONLY) && !object_in_construction (object))
|
||||||
{
|
{
|
||||||
g_warning ("%s: construct property \"%s\" for object '%s' can't be set after construction",
|
g_warning ("%s: construct property \"%s\" for object '%s' can't be set after construction",
|
||||||
G_STRFUNC, pspec->name, G_OBJECT_TYPE_NAME (object));
|
G_STRFUNC, pspec->name, G_OBJECT_TYPE_NAME (object));
|
||||||
@ -2327,7 +2297,7 @@ g_object_set_property (GObject *object,
|
|||||||
G_STRFUNC,
|
G_STRFUNC,
|
||||||
pspec->name,
|
pspec->name,
|
||||||
G_OBJECT_TYPE_NAME (object));
|
G_OBJECT_TYPE_NAME (object));
|
||||||
else if ((pspec->flags & G_PARAM_CONSTRUCT_ONLY) && !object_in_construction_list (object))
|
else if ((pspec->flags & G_PARAM_CONSTRUCT_ONLY) && !object_in_construction (object))
|
||||||
g_warning ("%s: construct property \"%s\" for object '%s' can't be set after construction",
|
g_warning ("%s: construct property \"%s\" for object '%s' can't be set after construction",
|
||||||
G_STRFUNC, pspec->name, G_OBJECT_TYPE_NAME (object));
|
G_STRFUNC, pspec->name, G_OBJECT_TYPE_NAME (object));
|
||||||
else
|
else
|
||||||
|
Loading…
x
Reference in New Issue
Block a user