Boost logo

Boost :

From: Trey Jackson (tjackson_at_[hidden])
Date: 2003-02-05 18:48:14

Peter Dimov wrote:
>The overhead is usually acceptable, even with a plain pthread_mutex.

Agreed. With that in mind, why wasn't the shared_ptr *also* protected
by a mutex?

>> Thereby making the simultaneous read/write safe (safe in that no
>> memory would be leaked b/c the pointers written/read).
>Consider this:
>// thread A
>// thread B

As you pointed out, there's no way for that to be thread safe with the
shared_ptr, but it's probably not possible to make it safe with *any*
type of pointer. That's not what I was trying to ask.

You *could* make all reasonable operations on pointers thread safe
with a mutex. (where reasonable = all the examples shown on the
boost::shared_ptr documentation).

Why wasn't that done?

if the reference count for a shared pointer is thread safe
in simultaneous write, why not make the pointer value thread safe as

from boost docs:
| boost::shared_ptr p, p3;
| // thread A
| p = p3; // reads p3, writes p
| // thread B
| p3.reset(); // writes p3, simultaneous read/write undefined

you've already got the mutex "penalty" in the counter.
why not pull it out of there, put it in the shared pointer,
and then you've got thread safe pointers. right?

i understand that there's no guarantee on what p will point to, but
we know it's not going to point to garbage - but it *will* be p3 or 0.

>> Which brings me to a third question.
>> Let's say I've got a class (e.g. shared_count) that I sometimes want
>> to be protected by a mutex, and sometimes not. Say, for instance, I
>> want it to be protected by default, but sometimes I want to avoid that
>> overhead b/c I know I'll be using it in an environment that's already
>> protected by a mutex (and can avoid the extra mutex overhead).
>Can you demonstrate this with an example?

I may have this a little wrong, but here's my shot at an example:

template <typename T> class shared_ptr;
  (which uses)
class counted_base;

class counted_base<class LockingStrategy = MutexLockingStrategy>;

template <typename T, class LockingStrategy = MutexLockingStrategy> class shared_ptr;
  (which specializes)

(where MutexLockingStrategy and NullLockingStrategy are defined in the
previous email)

So, you use a template for the counted_base class to define the type
of thread locking primitives you want to use.

Today's counted_base == tomorrow's counted_base<MutexLockingSTrategy>
in terms of functionality.

But, the flexibility allows the shared_ptr to avoid the mutex inside
the shared_ptr;

I started thinking about this with my own work.
I've got a query-tree class (2-D binary tree) that sometimes needs to
be thread-safe, and sometimes not - in the same executable.

e.g. I want to be able to do:

QT unsafe_tree;

QT<MutexLockingStragegy> thread_safe_tree;

and this applies to all sorts of containers/classes.

>> Just wondering if the above strategy could be used in the case of
>> shared_count, and if not, why not?
>Because of the extra LockingStrategy parameter. :-)

Yeah, but is there a technical reason for not doing something like the

I'm wondering what the downside would be?

The upsides I can see are:

1) pulls mutex details outside of the class
2) gets rid of ugly '#ifdef BOOST_HAS_THREADS' lines
3) allows different specializations of the (counted_base) class in the
   same binary

Obviously, the MutexLockingStrategy class would still have the ugly
#ifdef lines in it, but that's it.


Trey Jackson
"Instant gratification takes too long."
-- Carrie Fisher

Boost list run by bdawes at, gregod at, cpdaniel at, john at