From: Andrew Green (ag_at_[hidden])
Date: 2001-01-08 18:15:55
Andrew Green wrote:
>> If shared's ref count was >1 before we start these two sequences then we
>> don't have a problem. If shared's refcount _is_ 1 then the sequence of
>> instructions 1A through 1B must not overlap with the sequence 2A through 2B.
>> Individual atomic operations do not help in this scenario -- it seems to me
>> that there's no way to safeguard against this without a larger locking scope
>> than atomic ops provide.
Greg Colvin responded:
> It looks to me as if the [1B] above needs to go after the line
> shared.refCounts_ = local1.refCounts_;
> to be sure that local2.refCounts_ is consistent with local2.ptr_
> but I am still scratching my head at this example.
> I wonder if it would help to put the pointer and count fields
> together in a handle structure, and store a pointer to that in the
> smart pointer structure?
You're correct regarding the placement of 1B -- it should really have been
one statement later. I was basing my thoughts on a different set of code
which has the refcount in the referred-to object, and trying to map the
argument back to Dejan's code. In general, keeping the pointer to the object
and the refcount in separate entities, as in Dejan's implementation (and
most other samples I've seen) just makes things even harder to keep straight
-- there's now _two_ pointers to copy plus the ref count to manipulate when
If the strong and weak refcounts and the pointer were all kept in a single
intermediate handle object, then what Ptr<> references could be updated in
a single instruction. Which stil leaves the problem that we need to
atomically copy of the pointer to the handle _and_ increment the strong
reference count it contains.
Re William Kempf's comment:
> The performance of copies will be
> dreadfully impacted with out a lock free implementation.
Agreed. Benaphores can ameliorate the situation somewhat, requiring an
additional atomic_increment_and_test and an atomic_decrement_and_test
generally, and only hitting a real semaphore when there's contention, which
of course will be *really* rare (but devastating) in the situation we're
Note though that this problem only affects objects which can be assigned
_to_ across threads. If there's a shared object that's being assigned from I
think we still need to have the object pointer and its refcount in a single
structure, but the refcount of that shared object can't ever take on a value
that will be problematic. It might be that the count is not strictly
accurate during overlapping assignments, but it will be accurate after those
assignments have occurred, and won't have taken on the problematic value of
zero at any point in the interim.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk