Boost logo

Boost :

From: Andy Glew (glew_at_[hidden])
Date: 1999-07-27 14:19:10


>Yes, this is true enough. I also hate the unnecessary overhead when it comes to use STL

Sorry, I misremembered: although there is some thread clutter in the EGCS STL,
I have not seen it causing any performance problems. I have, however, seen
exception related clutter causing performance problems.

>However, still I feel that the issue I raised has not been answered at all.
>Imagine that you call a method (for simplicity let it be non-virtual) of an object.
>Of course, ***the object should be kept alive until you return from the call***

Fair enough, I misunderstood the level of the question.

I think that the gist of the answer is "We're using C++: if we wanted such
protection we would use a language system that supports it directly;
or, we would be using a proper GC system; or, we would have coded
it up ourselves."

The usual performance vs. safety issues apply. Multiple levels of thread safety:

(0) Non-thread safe. The objects' methods aren't mutually atomic: the user programmer
has to mutex them.

(1) Non-deallocated thread safe: the objects' methods, etc., are safe, i.e. mutually atomic
against each other for normal operation, but not against object deletion. E.g. adding,
erasing an element from a container may be thread safe (handwave about the
object contained), but delete is not.

(2) Deallocate thread safe: safe in the manner you describe above: safe against deallocation.

Actually, in general you must consider a matrix for relative atomicity, indicating which operations
can safely be initiated when another operation is running. Usually these matrices admit transitive
closure and are symmetric: i.e. if A and B are mutually atomic, and B and C are mutually atomic,
then A and C are mutually atomic, etc.

So much for theory. MY points are:
a) "Thread safety" is not an absolute. Atomicity is relative.
b) If we want to be accurate, we should specify the relative atomicity
    matrices.
c) Most people, even in multi-threaded environments, will not want
    to pay the price of maximum thread-safety. Intermediate levels of
    thread safety will be acceptable, such as "safe against everything
    but delete".

>Of course, this is not efficient (but thread-safe code can rarely be attributed to be efficient).
>Another idea is to limit accesses to the object to go through various smart pointers. This means
>that you should not be able to expose (and store) the address of the object (you can do this).

Probably the most general approach. Worth exploring.
I'd like to have a mix-in that restricts the address-of operator in this way:

    template<class T> class keepalive_ptr_only {
    public:
        keepalive_ptr<T> operator&();
        ...
    }

with implicit conversions from live_ptr<T> to keepalive_ptr<T>,
and a prohibition against using anything other than keepalive_ptr<T>
as a function argument.

I think that you can close this system by overloading ->, etc.

Best: since this is intrusive, the programmer would not be paying
for it unless he was pretty sure that this degree of safety was what
he wanted.

>but doing it in a semi threadsafe way is dangerous to say the least.

Maybe. Myself, I am comfortable with non-absolute safety, when I realized
that all such atomicity and ordering issues are relative.

I.e. given nearly any parallel programming model, I can show you a computer
architecture that violates its atomicity assumptions. Like: do you think that
aligned stores of 32 bit data quantities are atomic? The hardware goes to
some effort to make them appear to be so, but I can show you a few
plausible microarchitecture proposals that violate that rule. Unlikely to
be implemented by Intel in the near future - *I* wrote the manual section
promising that aligned 32 bit data stores in ordinary cacheable memory
would be atomic - but attractive.

>smart pointers are dangerous because people tend to think that they are safe.

Valid point.

>See comments above. I suggest to include a statement in the description of every piece of code if
>it is multi-thread safe. And sometimes, occasionally think about multi-thread safe versions.

Fair enough, except I suggest changing the default:

Always assume that code is not multithread safe or exception safe unless proven otherwise
(and, hopefully, tested - lots of "proofs" have more bugs than the code).

And don't hang out for absolute multithread safety. Consider intermediate
forms of multithread safety, such as the "multithread safe against everything
but delete" moel I mentioned above. Ideally, provide some compact symbolic
representation of the relative atomicity matrix --- however, I don't extend too much
hope for the latter, since at the moment such matrices are quite annoying to
generate.

I do have some hope, though, that notations such as relative atomicity matrices
and relative ordering matrices could be useful in computing the semantics of
libraries combined from different components.

===

Anyway, enough chatter. Got to find out why ^&$%^@#@ LILO is booting so
goddamned slowly. And then gotta send Reid the live_ptr code.


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