|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r54019 - trunk/boost/flyweight
From: joaquin_at_[hidden]
Date: 2009-06-17 14:58:07
Author: joaquin
Date: 2009-06-17 14:58:06 EDT (Wed, 17 Jun 2009)
New Revision: 54019
URL: http://svn.boost.org/trac/boost/changeset/54019
Log:
polished up [52457]
Text files modified:
trunk/boost/flyweight/refcounted.hpp | 47 ++++++++++++++-------------------------
1 files changed, 17 insertions(+), 30 deletions(-)
Modified: trunk/boost/flyweight/refcounted.hpp
==============================================================================
--- trunk/boost/flyweight/refcounted.hpp (original)
+++ trunk/boost/flyweight/refcounted.hpp 2009-06-17 14:58:06 EDT (Wed, 17 Jun 2009)
@@ -23,22 +23,20 @@
#include <boost/utility/swap.hpp>
/* Refcounting tracking policy.
- * The implementation deserves some explanation; values are equipped with a
- * reference count with the following semantics:
- * - 0: newly created value.
- * - n: (n-1) active references to the value.
- * When the number of references reaches zero, the value can be erased. The
- * exact protocol, however, is a little more complicated to avoid data races
- * like the following:
+ * The implementation deserves some explanation; values are equipped with two
+ * reference counts:
+ * - a regular count of active references
+ * - a deleter count
+ * It looks like a value can be erased when the number of references reaches
+ * zero, but this condition alone can lead to data races:
* - Thread A detaches the last reference to x and is preempted.
* - Thread B looks for x, finds it and attaches a reference to it.
* - Thread A resumes and proceeds with erasing x, leaving a dangling
* reference in thread B.
- * To cope with this, values are equipped with an additional count of threads
- * preempted during erasure. Such a preemption are detected by the preempting
- * thread by checking whether the reference count of the object is 1 (hence
- * the uncommon refcounting semantics distinguishing between a newly created
- * value and a value with no active references.
+ * Here is where the deleter count comes into play. This count is
+ * incremented when the reference count changes from 0 to 1, and decremented
+ * when a thread is about to check a value for erasure; it can be seen that a
+ * value is effectively erasable only when the deleter count goes down to 0.
*/
namespace boost{
@@ -61,13 +59,13 @@
~refcounted_value()
{
- /* count()>1 most likely indicates that the flyweight factory
+ /* count()!=0 most likely indicates that the flyweight factory
* has been destructed before some of the flyweight objects using
* it. Check for static initialization order problems with this
* flyweight type.
*/
- BOOST_ASSERT(count()<=1);
+ BOOST_ASSERT(count()==0);
}
refcounted_value& operator=(const refcounted_value& r)
@@ -86,11 +84,10 @@
long count()const{return ref;}
long add_ref()const{return ++ref;}
- bool release()const{return (--ref==1);}
+ bool release()const{return (--ref==0);}
- long count_deleters()const{return del_ref;}
void add_deleter()const{++del_ref;}
- void release_deleter()const{--del_ref;}
+ bool release_deleter()const{return (--del_ref==0);}
private:
Value x;
@@ -104,14 +101,8 @@
public:
explicit refcounted_handle(const Handle& h_):h(h_)
{
- switch(TrackingHelper::entry(*this).add_ref()){
- case 1: /* newly created object, make count()==2 (1 active reference) */
- TrackingHelper::entry(*this).add_ref();
- break;
- case 2: /* object was about to be erased, increment the deleter count */
- TrackingHelper::entry(*this).add_deleter();
- break;
- default:break;
+ if(TrackingHelper::entry(*this).add_ref()==1){
+ TrackingHelper::entry(*this).add_deleter();
}
}
@@ -143,11 +134,7 @@
private:
static bool check_erase(const refcounted_handle& x)
{
- if(TrackingHelper::entry(x).count_deleters()){
- TrackingHelper::entry(x).release_deleter();
- return false;
- }
- return true;
+ return TrackingHelper::entry(x).release_deleter();
}
Handle h;
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk