xxxxx
diff --git a/gobject/gobject.c b/gobject/gobject.c
index cef53a2..605588e 100644
--- a/gobject/gobject.c
+++ b/gobject/gobject.c
@@ -110,6 +110,7 @@
#define OPTIONAL_FLAG_LOCK (1 << 3) /* _OPTIONAL_BIT_LOCK */
#define OPTIONAL_FLAG_EVER_HAD_WEAK_REF (1 << 4) /* whether on the object ever g_weak_ref_set() was called. */
#define OPTIONAL_FLAG_NEEDS_NOTIFY (1 << 5) /* Corresponds to CLASS_NEEDS_NOTIFY(). */
+#define OPTIONAL_FLAG_FROZEN_IN_CONSTRUCTION (1 << 6) /* Whether we are OPTIONAL_FLAG_IN_CONSTRUCTION and froze the notify queue. */
/* We use g_bit_lock(), which only supports one lock per integer.
*
@@ -826,29 +827,41 @@
GDestroyNotify *destroy_notify,
gpointer user_data)
{
- GParamSpec *pspec = ((gpointer *) user_data)[0];
- gboolean in_init = GPOINTER_TO_INT (((gpointer *) user_data)[1]);
+ GObject *object = ((gpointer *) user_data)[0];
+ GParamSpec *pspec = ((gpointer *) user_data)[1];
+ gboolean is_notify = GPOINTER_TO_INT (((gpointer *) user_data)[2]);
GObjectNotifyQueue *nqueue = *data;
guint16 i;
if (!nqueue)
{
- if (!in_init)
+ guint flags;
+
+ if (!is_notify)
{
- /* We are not in-init and are currently not frozen. There is nothing
- * to do. We return FALSE to the caller, which then will dispatch
- * the event right away. */
+ /* We are called object_set_property() at a time when we expect to be
+ * frozen. Somebody messed up the ref-count for freeze/thaw. This is
+ * a bug. */
+ g_return_val_if_reached (GINT_TO_POINTER (FALSE));
+ }
+
+ flags = object_get_optional_flags (object);
+
+ if (!(flags & OPTIONAL_FLAG_IN_CONSTRUCTION))
+ {
+ /* We are no longer constructing and are not frozen. The user called
+ * g_object_notify(). We return FALSE here and out caller
+ * g_object_notify_by_spec_internal() will directly dispatch the
+ * notification. */
return GINT_TO_POINTER (FALSE);
}
- /* If we are "in_init", we always want to create a queue now.
- *
- * Note in that case, the freeze will be balanced at the end of object
- * initialization.
- *
- * We only ensure that a nqueue exists. If it doesn't exist, we create
- * it (and freeze once). If it already exists (and is frozen), we don't
- * freeze an additional time. */
+ /* We are still under construction, but not yet frozen due to that.
+ * We don't want to notify yet, so we freeze here. */
+#ifdef G_ENABLE_DEBUG
+ g_assert (!(flags & OPTIONAL_FLAG_FROZEN_IN_CONSTRUCTION));
+#endif
+ object_set_optional_flags (object, OPTIONAL_FLAG_FROZEN_IN_CONSTRUCTION);
nqueue = g_object_notify_queue_new_frozen ();
*data = nqueue;
*destroy_notify = g_free;
@@ -893,14 +906,18 @@
static gboolean
g_object_notify_queue_add (GObject *object,
GParamSpec *pspec,
- gboolean in_init)
+ gboolean is_notify)
{
gpointer result;
result = _g_datalist_id_update_atomic (&object->qdata,
quark_notify_queue,
g_object_notify_queue_add_cb,
- ((gpointer[]){ pspec, GINT_TO_POINTER (!!in_init) }));
+ ((gpointer[]) {
+ object,
+ pspec,
+ GINT_TO_POINTER (!!is_notify),
+ }));
return GPOINTER_TO_INT (result);
}
@@ -1814,6 +1831,7 @@
{
guint *p_flags;
gboolean needs_notify = CLASS_NEEDS_NOTIFY (class);
+ gboolean needs_freeze = (CLASS_HAS_PROPS (class) && needs_notify);
object->ref_count = 1;
object->qdata = NULL;
@@ -1824,8 +1842,10 @@
*p_flags = OPTIONAL_FLAG_IN_CONSTRUCTION;
if (needs_notify)
*p_flags |= OPTIONAL_FLAG_NEEDS_NOTIFY;
+ if (needs_freeze)
+ *p_flags |= OPTIONAL_FLAG_FROZEN_IN_CONSTRUCTION;
- if (CLASS_HAS_PROPS (class) && needs_notify)
+ if (needs_freeze)
{
/* freeze object's notification queue, g_object_new_internal() preserves pairedness */
g_object_notify_queue_freeze (object, TRUE);
@@ -2038,9 +2058,7 @@
if (!needs_notify)
return;
- in_init = (object_flags & OPTIONAL_FLAG_IN_CONSTRUCTION) != 0;
-
- if (g_object_notify_queue_add (object, pspec, in_init))
+ if (g_object_notify_queue_add (object, pspec, TRUE))
return;
/*