Jump to content
  • Advertisement
Sign in to follow this  
ElPeque2

help boost::bind and shared pointers

This topic is 3720 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have this problem. Im using boost::bind for programming the call-back mechanism for a gui system and to pass messages (possibly, delayed messages). My problem is, that when i bind member functions, if i specify the instance of the class as a shared_ptr, then i get memory leaks because the binding's shared_ptr to the instance keeps it alive, and it potentially produces cyclic references that in the current model, would be complicated to break. And of course, if i use raw pointers to the binding instances, then i'll get a crash if the instance has been destroyed and i try to execute the binding function. So what i would need, is to use bind with weak pointers, and just do nothing if locking it fails. I'm not sure how to do that, or how to assemble a good walkaround. I'd like it to be as automatic as possible. Thanks for your time, i appreciate any help :)

Share this post


Link to post
Share on other sites
Advertisement
Quote:
So what i would need, is to use bind with weak pointers, and just do nothing if locking it fails.
Can't do it directly, unfortunately. This is something I've really wanted for boost::bind and boost::signal for awhile. There's half-decent reasons behind it (no always-applicable response for dead ptrs), but I think the main problem is that it doesn't fall cleanly on any one side of the bind/signal/smart_ptr trifurcation.

A workaround is to boost::bind to a static function which takes a weak_ptr, locks it, and calls the non-static version. Heck, you could wrap this up in some template functions without much trouble. There's also other event libraries out there which don't suffer from this limitation, because they implement their own weak_ptr-like things.

Share this post


Link to post
Share on other sites
I don't think i could do the template wrap up you mention without breaking things. Im quite new to programming my own templates.

Someone at the boost maillist suggested me looking at the Thread Safe version of Signals. It seems you set up the signal to track the shared pointers, and automatically disconnects the ones that expire. I think i'll take a look at it.

But im still looking for more ideas, and thanks Sneftel for your time :).

PD: I'd appreciate some guidelines in case i decide to try to make the template wrapper you proposed.

Share this post


Link to post
Share on other sites
Quote:
Original post by ElPeque2
Someone at the boost maillist suggested me looking at the Thread Safe version of Signals. It seems you set up the signal to track the shared pointers, and automatically disconnects the ones that expire. I think i'll take a look at it.

That's the "trackable" thing. It works okay... but forces you to use raw, instead of shared, pointers. BTW, it's in main boost::signals; you don't need the thread safe version.

EDIT: Now that I look at it, thread-safe signals has discarded trackable in favor of weak_ptr. Awesome. Go with that.

Share this post


Link to post
Share on other sites
What do you mean by "thread-safe signals has discarded trackable in favor of weak_ptr."

http://www.comedi.org/projects/thread_safe_signals/libs/thread_safe_signals/doc/html/signals/tutorial.html#id2566661

you mean this:


deliverNews.connect(signal_type::slot_type(&NewsMessageArea::displayNews,
newsMessageArea, _1).track(newsMessageArea));


is no longer necesary?

Share this post


Link to post
Share on other sites
Oh, that's still necessary. What isn't necessary is making all your classes inherit from trackable, duplicating the ref-count stuff that shared_ptr already offers.

Share this post


Link to post
Share on other sites
this is the wrapper code i use - i avoid an exposed global get() type function since the weakly bound object could go out of scope between the getting of the underlying pointer and the call of the bound function/method (fundamental difference with shared_ptr get() binding). here, at the time of the call a strong reference is used else an exception is thrown. its convenient since with a multicast delegate (bound multimethod? ) type thing since we can just iterate in a try block and remove 'dangling' type functions.

#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>

using namespace std;
using namespace boost;

class A
{
public:
A() { }
virtual ~A() { }
void method( int value) { cout << "method() " << value << endl; }
};

template< typename T >
class from_weak_impl
{
public:
// result_type must defined and be const,
// we must return a strong ptr to prevent another thread unlocking between calls
typedef const shared_ptr< T> result_type;
weak_ptr< T> p;
inline from_weak_impl( const weak_ptr< T> &p0) : p( p0) { }
inline from_weak_impl( const shared_ptr< T> &p0) : p( p0) { }
inline result_type operator ()() const {
// throws if bad...
return shared_ptr< T>( p);
}
};

template<class T>
inline from_weak_impl< T> from_weak( const weak_ptr<T> & p)
{
return from_weak_impl< T>( p);
}

template<class T>
inline from_weak_impl< T> from_weak( const shared_ptr<T> & p)
{
return from_weak_impl< T>( p);
}

int main()
{
function< void( int) > f;

{
shared_ptr< A> a( new A ) ;
shared_ptr< A> sa = a;
weak_ptr< A> wa = a;

f = bind( &A::method, sa, _1 ); // strong
f = bind( &A::method, bind( from_weak( wa)), _1 ); // weak
f = bind( &A::method, bind( from_weak( sa)), _1 ); // weak
}

// should throw since object a is out of scope
f( 123);
}




Share this post


Link to post
Share on other sites
Quote:
Original post by loufoque
It seems what you want is enable_shared_from_this.
How so?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!