diff --git a/lib/wp/object.c b/lib/wp/object.c index 1ca284a8..18198017 100644 --- a/lib/wp/object.c +++ b/lib/wp/object.c @@ -143,6 +143,7 @@ struct _WpObjectPrivate WpObjectFeatures ft_active; GQueue *transitions; // element-type: WpFeatureActivationTransition* GSource *idle_advnc_source; + GWeakRef ongoing_transition; }; enum { @@ -161,6 +162,7 @@ wp_object_init (WpObject * self) g_weak_ref_init (&priv->core, NULL); priv->transitions = g_queue_new (); + g_weak_ref_init (&priv->ongoing_transition, NULL); } static void @@ -189,6 +191,7 @@ wp_object_finalize (GObject * object) g_warn_if_fail (g_queue_is_empty (priv->transitions)); g_clear_pointer (&priv->transitions, g_queue_free); g_clear_pointer (&priv->idle_advnc_source, g_source_unref); + g_weak_ref_clear (&priv->ongoing_transition); g_weak_ref_clear (&priv->core); /* everything must have been deactivated in dispose() */ @@ -309,17 +312,24 @@ static gboolean wp_object_advance_transitions (WpObject * self) { WpObjectPrivate *priv = wp_object_get_instance_private (self); - WpTransition *t; /* clear before advancing; a transition may need to schedule a new call to wp_object_advance_transitions() */ g_clear_pointer (&priv->idle_advnc_source, g_source_unref); - while ((t = g_queue_peek_head (priv->transitions))) { - wp_transition_advance (t); - if (!wp_transition_get_completed (t)) + while (TRUE) { + g_autoptr (WpTransition) t = g_weak_ref_get (&priv->ongoing_transition); + if (t) { + wp_transition_advance (t); + if (!wp_transition_get_completed (t)) + break; + } + + if (g_queue_is_empty (priv->transitions)) break; - g_object_unref (g_queue_pop_head (priv->transitions)); + + g_weak_ref_set (&priv->ongoing_transition, + g_queue_pop_head (priv->transitions)); } return G_SOURCE_REMOVE; @@ -382,7 +392,7 @@ wp_object_activate_closure (WpObject * self, wp_transition_set_source_tag (transition, wp_object_activate); wp_transition_set_data (transition, GUINT_TO_POINTER (features), NULL); - g_queue_push_tail (priv->transitions, g_object_ref (transition)); + g_queue_push_tail (priv->transitions, transition); if (!priv->idle_advnc_source) { wp_core_idle_add (core, &priv->idle_advnc_source, @@ -454,6 +464,7 @@ wp_object_update_features (WpObject * self, WpObjectFeatures activated, WpObjectPrivate *priv = wp_object_get_instance_private (self); guint old_ft = priv->ft_active; + g_autoptr (WpTransition) t = NULL; priv->ft_active |= activated; priv->ft_active &= ~deactivated; @@ -464,7 +475,8 @@ wp_object_update_features (WpObject * self, WpObjectFeatures activated, g_object_notify (G_OBJECT (self), "active-features"); } - if (!g_queue_is_empty (priv->transitions) && !priv->idle_advnc_source) { + t = g_weak_ref_get (&priv->ongoing_transition); + if ((t || !g_queue_is_empty (priv->transitions)) && !priv->idle_advnc_source) { g_autoptr (WpCore) core = g_weak_ref_get (&priv->core); g_return_if_fail (core != NULL);