From 17a558a386d41444b926f9e8bec46f74d437745a Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Wed, 6 Jul 2011 12:28:07 +0100 Subject: [PATCH] cogl-pipeline: Fix reference counting on promoting weak parents When a copy is made of a weak pipeline it tries to promote the weak parent by taking a reference on that weak pipeline's parent. However promote_weak_ancestors was instead always taking a reference on the first parent, regardless of whether it was weak. The corresponding revert_weak_ancestors function which is supposed to undo the effect of promote_weak_ancestors only unref'd the parent if was weak. This meant that any non-weak pipeline copy would end up leaking a reference on its parent. This patch changes both functions to have a similar loop. It loops through all of the parents of the pipeline until it finds one that is not weak and refs or unrefs the *parent* of that pipeline instead of the pipeline itself. Signed-off-by: Robert Bragg --- cogl/cogl-pipeline.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/cogl/cogl-pipeline.c b/cogl/cogl-pipeline.c index db9d29b12..ce0820321 100644 --- a/cogl/cogl-pipeline.c +++ b/cogl/cogl-pipeline.c @@ -375,37 +375,40 @@ _cogl_pipeline_promote_weak_ancestors (CoglPipeline *strong) g_return_if_fail (!strong->is_weak); - for (n = COGL_PIPELINE_NODE (strong)->parent; n; n = n->parent) - { - CoglPipeline *pipeline = COGL_PIPELINE (n); + /* If the parent of strong is weak, then we want to promote it by + taking a reference on strong's grandparent. We don't need to take + a reference on strong's direct parent */ - cogl_object_ref (pipeline); + if (COGL_PIPELINE_NODE (strong)->parent == NULL) + return; - if (!pipeline->is_weak) - return; - } + for (n = COGL_PIPELINE_NODE (strong)->parent; + /* We can assume that all weak pipelines have a parent */ + COGL_PIPELINE (n)->is_weak; + n = n->parent) + /* 'n' is weak so we take a reference on its parent */ + cogl_object_ref (n->parent); } static void _cogl_pipeline_revert_weak_ancestors (CoglPipeline *strong) { - CoglPipeline *parent = _cogl_pipeline_get_parent (strong); CoglPipelineNode *n; g_return_if_fail (!strong->is_weak); - if (!parent || !parent->is_weak) + /* This reverts the effect of calling + _cogl_pipeline_promote_weak_ancestors */ + + if (COGL_PIPELINE_NODE (strong)->parent == NULL) return; - for (n = COGL_PIPELINE_NODE (strong)->parent; n; n = n->parent) - { - CoglPipeline *pipeline = COGL_PIPELINE (n); - - cogl_object_unref (pipeline); - - if (!pipeline->is_weak) - return; - } + for (n = COGL_PIPELINE_NODE (strong)->parent; + /* We can assume that all weak pipelines have a parent */ + COGL_PIPELINE (n)->is_weak; + n = n->parent) + /* 'n' is weak so we unref its parent */ + cogl_object_unref (n->parent); } /* XXX: Always have an eye out for opportunities to lower the cost of