Boost logo

Boost :

From: Peter Dimov (pdimov_at_[hidden])
Date: 2003-05-25 07:58:16


William E. Kempf wrote:
> Peter Dimov said:
>> Alexander Terekhov wrote:
>>> Try to convince Dimov that policy-based designs/interfaces aren't
>>> that bad; and that, in general, the stuff managed by smart pointers
>>> isn't necessarily process-wide/thread-shared stuff "by default"...
>>> like global heap, current working directory, etc.
>>
>> Policy based designs aren't bad. It's just that when I look at
>> boost::shared_ptr I see std::shared_ptr. The existing practice is
>> that things in the standard library are as thread safe as an int "by
>> default". Nobody complains that std::string should have a threading
>> model parameter since it can be (much) more efficient if it's only
>> accessed from a single thread.
>
> Things in the standard library aren't thread safe,

Yes they are. :-)

> unless an implementation chooses to make it so.

They do. When they forget (cough MSVC6 STL), the real world kindly reminds
them by submitting several quintillion bug reports.

> The standard doesn't specify
> *anything* about threads, including the thread safety of any
> operations.

Indeed. I've been careful to use "existing practice" and not to refer to any
legalese.

> Obviously, everyone knows that. I'm stating it now to make a point.
> When the standard finally does have something to say about threads,
> I'm not sure that it's a given that we'll be able to say "things in
> the standard library are as thread safe as an int" (or what many call
> thread-neutral). If some standard "thing" *must* rely on shared state
> (not a given for string, like it is for shared_ptr), I can certainly
> have sympathy with those who want control over whether or not a
> particular instance of this thing needs any synchronization.

It's not as simple as you make it seem.

There are three separate problems that I see with shared_ptr WRT threading.

1. A thread safe shared_ptr cannot interoperate with its thread unsafe
counterpart. This is technically an ODR violation, but it is common enough
that it deserves support. To provide a concrete example, when a Boost
library that uses shared_ptr is built on a Windows compiler using the single
threaded runtime, but the application that uses that library is using the
multithreaded runtime (or vice versa), some shared_ptr operations hang
waiting forever for a spinlock that isn't there.

2. The pthread_mutex based version is suboptimal, both space- and
performance wise. The problem here is that it is difficult to fix portably.
On most platforms with a suboptimal (for our purposes, not in general)
pthread_mutex, it is possible to implement a platform-specific shared_ptr
that is no more than ~1.2 - 2.0 times slower than the unsynchronized version
and doesn't use much extra space. In 95%+ of the cases (statistic made up on
the spot) this performance difference doesn't even register on the profiler.
Maybe one day we'll have a pthread_refcount_t. ;-)

3. The third problem is not technical but psychological/PR. Many shared_ptr
users try hard to avoid the synchronization overhead without researching its
actual impact on their code. Often shared_ptr operations are a relatively
small amount of the code and don't affect its overall performance. Also,
depending on the creation:copy ratio, it is often the allocator that is the
bottleneck and not the count synchronization.

This problem is fairly delicate since you can't just tell people to profile
their code and get back to you. There is always the possibility that they
have, indeed, profiled their code beforehand and found a real problem, and
the "profile" answer is offensive and condescending.

All that said.

My preferred solution to (1) is to just make it work wherever possible, and
to (2) is to make the synchronized version fast/tight enough. This will
hopefully take care of (3).

The good thing about providing a threading model policy takes care of (3)
instantly, but it doesn't solve (1) in general, and it doesn't solve (2). In
fact, by allowing people to sweep (2) under the carpet, it takes the
pressure off the implementors to ever fix (2).

So I believe that long term, it is in the best interest of the C++ community
to not introduce a threading model policy. We'll continue to receive user
complaints until (2) is fixed, though. :-(


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