Boost logo

Boost Users :

Subject: Re: [Boost-users] How can I have an object-specific and thread-specific pointer?
From: Vicente J. Botet Escriba (vicente.botet_at_[hidden])
Date: 2011-11-17 01:51:12


Le 13/11/11 00:00, Phillip Hellewell a écrit :
> Hi,
>
> My class contains a member var that is a little buffer used as a
> cache. Instances of this class are used concurrently (referenced
> through a shared_ptr).
>
> I would like to switch my buffer to a thread_specific_ptr, but there
> are two big problems with using thread_specific_ptr as a member var:
The lifetime of your objects and the cache seems to be different. Have
you tried to isolate the buffer (cache) in a static thread_specific_ptr?
> 1. There is a memory leak when my object goes away, because by design
> only one of the pointers gets cleaned up (the one for the thread that
> happens to delete the object).
> 2. There is undefined behavior when a new object gets created that
> happens to be allocated at the same address as a previously freed
> one. get( ) could return a pointer to a buffer that goes with an old
> (now freed) object.
Yes, this is a know bug (feature for Anthony), that prevents from using
them as member objects.
>
> I try not to question the wisdom of the thread_specific_ptr authors,
> but given these two issues, especially #2, I have to conclude that
> thread_specific_ptr is only suitable for statics / globals. It is
> wholly unfit to be used as a member variable (except in a singleton
> class I guess).
>
> The next best thing I can think of for my class is to just have a
> std::map<thread_id, void*>, with synchronized access of course, and I
> clean up all the pointers in the map in the DTOR. That would work
> just great, except I really do need the pointers to also get cleaned
> up (and removed from my map) when the corresponding threads go away.
> Some of my objects can live a very long time, whilst threads get
> created and destroyed off and on, so without this functionality the
> map could grow indefinitely.
>
> So I'm stuck. I can't use thread_specific_ptr because it won't clean
> up everything when my object goes away, and I can't use a map because
> it won't clean up anything when a thread goes away. Is there an easy
> solution to this?
Note that your map is equivalent to a static thread_specific_ptr, that
present no evident advantages.
>
> If there were some way for me to hook up a callback directly to the
> thread cleanup function, I could add a callback to remove it from my
> map when the thread goes away. But I'd also need the ability to
> remove that callback in my DTOR. Does boost provide any way to do this?
Boost.Thread provides a non member function at_thread_exit()

#include <boost/thread/thread.hpp>
template<typename Callable> void at_thread_exit(Callable func);

Effects:

    A copy of |func| is placed in thread-specific storage. This copy is
    invoked when the current thread exits (even if the thread has been
    interrupted).

Postconditions:

    A copy of |func| has been saved for invocation on thread exit.

Throws:

    |std::bad_alloc| if memory cannot be allocated for the copy of the
    function, |boost::thread_resource_error| if any other error occurs
    within the thread library. Any exception thrown whilst copying
    |func| into internal storage.

Is this what you were looking for?
>
> I can't be the first person to want a thread-specific, object-specific
> pointer, can I?
>
>
My advice is use the static thread_specific_ptr ;-)

Best,
Vicente



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net