boost::bind and shared pointers

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 :)

Alejandro Martínez wrote:
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.
I think you should look at the thread_safe_signals library.

Alejandro Martínez <elpeque2 <at> gmail.com> writes:
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 :)
If you want boost::bind to work with weak_ptr then just add the following code before using bind. #include <boost/bind.hpp> #include <boost/function.hpp> #include <boost/weak_ptr.hpp> #include <boost/shared_ptr.hpp> #include <boost/preprocessor/inc.hpp> #include <boost/preprocessor/iteration/local.hpp> #include <boost/preprocessor/control/expr_if.hpp> #include <boost/preprocessor/punctuation/comma_if.hpp> #include <boost/preprocessor/repetition/enum_params.hpp> #include <boost/preprocessor/repetition/enum_shifted_params.hpp> #ifndef MAX_WEAK_FUNCTOR_ARGS #define MAX_WEAK_FUNCTOR_ARGS 10 #endif namespace detail { struct do_nothing { typedef void result_type; void operator()() const {} }; template <class T> struct weak_ptr_wrapper { explicit weak_ptr_wrapper(const boost::weak_ptr<T>& p) : p_(p) {} #define BOOST_PP_LOCAL_MACRO(N) \ BOOST_PP_EXPR_IF(N, template <) \ BOOST_PP_ENUM_PARAMS(N, class Q) \ BOOST_PP_EXPR_IF(N, >) \ boost::function<void( BOOST_PP_ENUM_PARAMS(N, Q) )> \ operator ->* (void (T::*fun)( BOOST_PP_ENUM_PARAMS(N, Q))) \ { \ if(boost::shared_ptr<T> p = p_.lock()) \ return boost::bind(fun, p BOOST_PP_COMMA_IF(N) \ BOOST_PP_ENUM_SHIFTED_PARAMS \ (BOOST_PP_INC(N), _)); \ else \ return boost::bind(do_nothing()); \ } #define BOOST_PP_LOCAL_LIMITS (0, MAX_WEAK_FUNCTOR_ARGS) #include BOOST_PP_LOCAL_ITERATE() private: boost::weak_ptr<T> p_; }; } namespace boost { template <class T> ::detail::weak_ptr_wrapper<T> get_pointer(const weak_ptr<T>& ptr) { return ::detail::weak_ptr_wrapper<T>(ptr); } } And here is the test: #include <iostream> struct foo { void f() { std::cout << "Hello" << std::endl; } }; int main() { boost::shared_ptr<foo> p(new foo); boost::weak_ptr<foo> w(p); boost::function<void()> f(bind(&foo::f, w)); f(); // prints "Hello" p.reset(); f(); // does nothing } It does not have the best performance because boost::function is created each time you call functor, but it can be easily improved by writing your own function wrapper and using it instead of boost::function as a return value from weak_ptr_wrapper::operator->. HTH, Roman Perepelitsa.
participants (3)
-
Alejandro Martínez
-
Nat Goodspeed
-
Roman Perepelitsa