Boost logo

Boost :

From: Tyson Whitehead (twhitehe_at_[hidden])
Date: 2004-07-09 12:56:20


Russell Hind wrote:
> If you're referring to the ref-counted shared_ptr, then it has two
> counts it needs to keep track of, strong_count and weak_count, so
> InterlockedXXXXXX can't be used. Therefore the 'spin-lock' was
> introduced IIUC.

I like the looks of the 'shared_count_x86_exp2.hpp' code. I can't see how
you could implement the 'atomic_conditional_increment' function with the
atomic primitives supplied by gcc (atomicity.h) or the Linux kernel
(atomic.h).

The problem the weak pointers introduce is syncronization between the two
counters (as Russell observed). I believe, however, that this is only an
issue in 'add_ref_lock'. This is because we really have two interfaces
here. A weak pointer interface and a strong pointer interface.

A program that calls the strong interface from a weak pointer is in error
(and would cause problems in the current implementation under the right
conditons). Likewise for one that uses the weak interface from a strong
pointer.

Thus we can assume:
1) Code that calls a strong interface routine is telling us that both
use_count_ and weak_count_ will not be concurrently decremented to zero by
another thread (because our thread has at least one strong reference).
2) Code that calls a weak interface routine is telling us that the
weak_count_ will not be concurrently decrement to zero by another thread
(because our thread has at least one weak reference).

If I am correct then, we could still do the following (as Windows, Linux,
and gcc all provided atomic increment/decrement functions):

// Strong interface

void add_ref_copy(){
  atomic_increment(use_count_);
}

void release(){
  if(atomic_decrement(use_count_)) return;
  
  dispose();
  weak_release();
}

// Weak interface

void add_ref_lock(){
  mutex_type::scoped_lock lock(mtx_);

  if(atomic_increment(use_count_) == 1){
    --use_count_;
    boost::throw_exception(boost::bad_weak_ptr());
  }
}

void weak_add_ref(){
  atomic_increment(weak_count_);
}

void weak_release(){
  if(atomic_decrement(weak_count_)) return;

  destruct();
}

-T

NOTE: The gcc/Linux atomic operations return the prior value. The Windows
operations return the new value. The above code uses the Windows style.

-- 
 Tyson Whitehead  (-twhitehe_at_[hidden] -- WSC-)
 Computer Engineer                        Dept. of Applied Mathematics,
 Graduate Student- Applied Mathematics    University of Western Ontario,
 GnuPG Key ID# 0x8A2AB5D8                 London, Ontario, Canada

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk