Alejandro MartÃnez 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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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 \
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 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.