I have an application where I need to pass "this" in a callback belonging to a class to a function using a shared_ptr in another thread In code: struct Data { Data( void* p ) : ptr( p ) { } boost::shared_ptr<void> ptr; }; void threadA( Data* d ) { boost::shared_ptr<void> ptr( d->ptr ); delete d; // use ptr } class A { void init_thread() { Data* data = new Data( this ); boost.thread t( boost::bind( threadA, data ) ); } }; The problem is obvious. Once threadA closes, the shared ptr is destroyed as its count is 0 and as it points to the this of class A this gets deleted too. However my class A is still active and should not get deleted. How can I work around this?
Here's a compilable version of the program that shows the crash due to
the ref. count reaching 0 in the thread.
#include
Gesendet: Montag, 09. September 2013 um 23:05 Uhr
Von: "Gonzalo Garramuno"
Hi In your case a is a stack variable that should never be deleted. You should never use a shared_ptr for that. Let's assume, your local variable a was only for showing the problem, but in fact your real code only uses heap allocated objects... Then you should NOT pass a void* to the constructor of Data but a shared_ptr<void>. The caller would then keep that shared_ptr around until it's own calls to the object are done... See modified code below. Regards, Steffen
#include
#include #include struct Data { Data( boost::shared_ptr<void>* p ) : ptr( p ) { }
boost::shared_ptr<void> ptr; };
void threadA( Data* d ) { boost::shared_ptr<void> ptr( d->ptr ); delete d; // use ptr }
class A : public boost::enable_shared_from_this<void> { public: void init_thread() { Data* data = new Data( shared_from_this<void>() ); boost::thread t( boost::bind( threadA, data ) ); }
void sleep() { timespec req; req.tv_sec = 3; req.tv_nsec = 0; nanosleep( &req, NULL ); } };
int main() { { A *a = new A(); boost::shared_ptr<void> x = a; a->init_thread(); a->sleep(); } // end of scope of x return 0; }
In your st, sruct Data, make the ptr a shared_ptr with custom deleter which
does nothing.
Mateusz Loskot
(Sent from mobile, apology for top-posting and broken quotes)
On 9 Sep 2013 21:55, "Gonzalo Garramuno"
I have an application where I need to pass "this" in a callback belonging to a class to a function using a shared_ptr in another thread
In code:
struct Data { Data( void* p ) : ptr( p ) { }
boost::shared_ptr<void> ptr; };
void threadA( Data* d ) { boost::shared_ptr<void> ptr( d->ptr ); delete d; // use ptr }
class A { void init_thread() { Data* data = new Data( this ); boost.thread t( boost::bind( threadA, data ) ); } };
The problem is obvious. Once threadA closes, the shared ptr is destroyed as its count is 0 and as it points to the this of class A this gets deleted too. However my class A is still active and should not get deleted. How can I work around this?
______________________________**_________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/**mailman/listinfo.cgi/boost-**usershttp://lists.boost.org/mailman/listinfo.cgi/boost-users
On Mon, Sep 9, 2013 at 4:55 PM, Gonzalo Garramuno
I have an application where I need to pass "this" in a callback belonging to a class to a function using a shared_ptr in another thread
Why? Who wrote the callback: you or someone else? If you did, then you can do whatever makes sense.
In code:
struct Data { Data( void* p ) : ptr( p ) { }
boost::shared_ptr<void> ptr; };
Three things. 1) I'd make ptr private. 2) I'd make that constructor explicit. You do not want implicit casts happening elsewhere in your code. 3) I'd normally use class instead of struct, unless there was a really good reason to use struct.
void threadA( Data* d ) { boost::shared_ptr<void> ptr( d->ptr ); delete d; // use ptr }
class A { void init_thread() { Data* data = new Data( this ); boost.thread t( boost::bind( threadA, data ) ); } };
This is usually a really bad idea. First, I'd make data and t private data members (and data can then be a smart pointer holding a pointer to an instance of type Data), and I would generally not give a data member a smart pointer to the class it is a part of. What is not clear is whether object t needs a pointer to an instance of class A or an instance of class data. Worse, in your subsequent post, where you show code that will compile, your instance of class A is on the stack, and yet your automatic variable data makes a smart pointer to it. I have never tried that, but I'd expect that to produce rather bad results. ;-) If you make data a data member of class A, and a smart pointer to an instance of type Data at that, then, if your callback needs a smart pointer to an object containing any data the thread needs, you can pass data to it instead of a smart pointer to an instance of type A. I always give ownership of every object I create on the heap to a smart pointer (and I never do that for an object on the stack), and always take care to avoid cyclic ownership (i.e. a case of object A having a smart pointer to object B while object b has a smart pointer to object A (and that can get tricky when there are multiple objects of multiple classes involved in complex interactions). You might do a search on the letter/envelop programming idiom: a common programming idiom in C++. So, second, I'd look at passing a smart pointer to an instance of type Data to the thread. HTH Ted
The problem is obvious. Once threadA closes, the shared ptr is destroyed as its count is 0 and as it points to the this of class A this gets deleted too. However my class A is still active and should not get deleted. How can I work around this?
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (5)
-
Gonzalo Garramuno
-
Jens Weller
-
Mateusz Loskot
-
Steffen Heil (Mailinglisten)
-
Ted Byers