Boost logo

Boost :

From: Dave Abrahams (abrahams_at_[hidden])
Date: 1999-12-26 17:10:18


Giora Unger wrote:

> 1. As far as I understand, the library is NOT thread safe.
> Am I wrong ?
> For example, let's examine line 169 in smart_ptr.h:
> if (--*pn == 0) { delete px; }
> I believe, that in case of two threads concurrently accessing
> this line (the reset() method), and an initial reference count==2,
> then a crash is possible: if both decrements occur before both
> comparisons, resulting in two deletion attempts.

Well, if everything is OK up to that point, you'll have a leak, not a
double-deletion, because there will never be fewer references than
shared_ptrs needing to be destroyed. If the shared_ptr is copied just as
the last reference is deleted, however, you can get the double-deletion you
were referring to when the copy is destroyed. In principle, though, this
should never happen: one thread should never copy an object (I'm talking
about the shared_ptr, not the thing it refers to) which might already be
destroyed in another thread.

> Do you, by any chance, have a list of changes necessary for
> making the library thread-safe ?

Nobody has done this yet, in part because threading is not defined
platform-independently in the language (each platform which supports
threading has its own API) and nobody has contributed a platform-neutral
threading library to boost. If you want to take a crack at it for your
platform, the lines you cite which decrement and test the reference count
are probably the only ones which need work. You just need to be sure that
the decrement and test are done as a single atomic unit. On some
architectures there are atomic test-and-set instructions which can be used
to do the job. If you don't have that facility, you'll need to use mutexes,
which are generally much less efficient.

[If you don't care that all of the destructors get executed immediately,
there is a version of shared_ptr currently under construction which
implements a form of garbage-collection and could probably be adapted to
solve the leak problem]

> 2. I'm developing in Microsoft VC++6.0, and in the boost/config.h,
> line 168, the BOOST_NO_MEMBER_TEMPLATE_FRIENDS
> is defined.
> Hence, all the private data members of my shared_ptr become
> public.
> Why is that ? Could you please elaborate about the trick with
> this parameter (there is a documentation, which I don't understand).
> How can I omit this undesired exposure, without causing any harm
> to the Smart Pointers implementation ?

The lines to which you refer are:

    #if !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS )
    private:

It seems to me that it ought to be changed to

    #if defined(BOOST_NO_MEMBER_TEMPLATES) \
        || !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS )
    private:

[While we're at it, I think we ought to move the #define for
BOOST_NO_MEMBER_TEMPLATES from smart_ptr.hpp into config.hpp -- comments?]

> And some minor questions:
> 3. What is scoped_ptr good for ? Isn't it included in shared_ptr ?
> In other words - assume I use shared_ptr, is there any use for
> scoped_ptr for me ?

Did you read the documentation
(http://www.boost.org/libs/smart_ptr/scoped_ptr.htm)? It says, among other
things:

    Because scoped_ptr is so simple, in its usual implementation every
    operation is as fast as a built-in pointer and has no more space
    overhead that a built-in pointer.

shared_ptr doesn't have this property. You might use scoped_ptr to implement
a handle/body structure which avoids exposing the body (implementation) in
the header file:

class handle
{
public: // simple forwarding functions to the body class
    void f();
    void g(int);
private:
    boost::scoped_ptr<body> m_p;
};

> 4. The same for arrays - is shared_array used simple for arrays,
> in contrast to simple pointers to objects ? If so - what's between
> it and scoped_array ?

The answer is analogous to the above

> 5. In your view, how should a comparison to NULL be performed ?
> I found out that either an explicit cast, e.g.: (ILinePtr)NULL,
> or an isNull() method are the options. So I added isNull() method.
> Did I miss anything ?

Yes: use get() to retrieve the raw pointer and compare it with 0 (or NULL,
if you prefer). You will probably be happier in the long run if you modify
boost code as little as possible, or you'll be rolling your isNull change
back into the boost code whenever there is an update to boost. On the other
hand, if you add thread-safety to shared_ptr, please submit it to boost so
we can use it ;)

> 6. What is the line - typedef T element_type; (e.g., line 111)
> good for ? Commenting it out doesn't seem to influence.
> Is it safe to comment it out ?

It can be used for generic programming. Since it is harmless, you might want
to leave it alone unless there's a compelling reason to change it, for
reasons mentioned above.

Hope this helps,
-Dave


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