diff options
author | Neil Roberts <neil@linux.intel.com> | 2011-07-06 12:45:26 +0100 |
---|---|---|
committer | Neil Roberts <neil@linux.intel.com> | 2011-07-07 02:10:24 +0100 |
commit | 2cfe64db73c437f8115b6f056d083072df00434b (patch) | |
tree | 12fae63400c2831766003c710653f2fcaa5f2e20 | |
parent | a8af207ddcf535f9b1d0a2e99999a9d68b06ea60 (diff) | |
download | clutter-2cfe64db73c437f8115b6f056d083072df00434b.tar.gz |
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.
This is cherry-picked from 17a558a386 on Cogl git master.
-rw-r--r-- | clutter/cogl/cogl/cogl-pipeline.c | 39 |
1 files changed, 21 insertions, 18 deletions
diff --git a/clutter/cogl/cogl/cogl-pipeline.c b/clutter/cogl/cogl/cogl-pipeline.c index acce53683..5f2024ad2 100644 --- a/clutter/cogl/cogl/cogl-pipeline.c +++ b/clutter/cogl/cogl/cogl-pipeline.c @@ -394,37 +394,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) + /* 'pipeline' 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) - return; - - for (n = COGL_PIPELINE_NODE (strong)->parent; n; n = n->parent) - { - CoglPipeline *pipeline = COGL_PIPELINE (n); + /* This reverts the effect of calling + _cogl_pipeline_promote_weak_ancestors */ - cogl_object_unref (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) + /* 'pipeline' is weak so we take a reference on its parent */ + cogl_object_unref (n->parent); } /* XXX: Always have an eye out for opportunities to lower the cost of |