Avoiding a circular reference of boost::functions

Hello, I am using boost::functions to provide a simple event system, but have come across a problem. I have two classes that need to communicate with each other, CGUI and CEventHandler. Their instances are both shred_ptrs owned by a third class, CCore. To establish comms, I am passing boost::functions which have been bound to members of the two classes: //--------------------- typedef std::vector<boost::any> many // CCore.cpp snippet boost::function<bool(many&)> cb = m_eventHandler->RegisterGUICallback( boost::bind( &IGUIInterface::HandleEventMessage, m_gui, _1 ) ); m_gui->RegisterEventHandler( cb ); // CEventHandler.cpp snippet // boost::function<bool(many&) m_guiTx declared in .h boost::function<bool(many&)> CEventHandler::RegisterGUICallback(boost::function<bool(many&)> f) { // MEM LEAK IS HERE - A circular reference? m_guiTx = f; return boost::bind(&CEventHandler::HandleGUIRx, this, _1); } // CGUI.cpp snippet // boost::function<bool(many&) eventHandlerCallback declared in .h void CGUI::RegisterEventHandler( boost::function<bool(many&)> cb ) { m_eventHandlerCallback = cb; m_log->GUI("EventHandler callback registered. Testing...\n");//, s ); std::string message = "This was sent from CGUI::RegisterEventHandler\n"; int id = 43; many msg; boost::any _message = message; boost::any _id = id; msg.push_back(_id); msg.push_back(_message); m_eventHandlerCallback(msg); } //----------------------------------------------------- As you can see, CCore binds a public member function of m_gui and passes it to the eventhandler, where it is stored and used to send events. The event handler returns its own member function, bound to this, which CCore duly passes to m_gui. Now both classes hold objects with refs to each other, and the program does a big memory dump when it is ended, on win32 with MSVC2005. I envisage this is because the shared_ptrs holding the instances of CGUI and CEvenHandler are not destructing at program close. Commenting out the line: m_guiTx = f; eliminates the issue. What is a better way to achieve this? Thanks Simon

It looks to me like the problem is the binds using shared_ptrs as instance pointers. Boost.Bind takes a copy of the shared_ptr while constructing the bind object (which is used to construct the funcion object). You then pass the function object to the GUI/event handler, which then contains a shared_ptr to the event handler/GUI respectively - as a shared_ptr is an ownership link, that this means that the GUI 'owns' the event handler and vice versa. An option would be to perform those binds using raw pointers - for example, use m_gui.get() rather than just m_gui. That would prevent the 'ownership' links being created. The smart pointer library *does* offer weak_ptr as a non-owning smart pointer, but I don't know if Boost.Bind works with that - worth investigating, though? HTH Stuart Dootson On Sat, Jul 12, 2008 at 12:14 PM, Simon Pickles <sipickles@googlemail.com> wrote:
Hello,
I am using boost::functions to provide a simple event system, but have come across a problem.
I have two classes that need to communicate with each other, CGUI and CEventHandler. Their instances are both shred_ptrs owned by a third class, CCore.
<snip>
As you can see, CCore binds a public member function of m_gui and passes it to the eventhandler, where it is stored and used to send events.
The event handler returns its own member function, bound to this, which CCore duly passes to m_gui.
Now both classes hold objects with refs to each other, and the program does a big memory dump when it is ended, on win32 with MSVC2005. I envisage this is because the shared_ptrs holding the instances of CGUI and CEvenHandler are not destructing at program close.
Commenting out the line: m_guiTx = f;
eliminates the issue.
What is a better way to achieve this?
Thanks
Simon

Simon Pickles wrote:
I am using boost::functions to provide a simple event system, but have come across a problem.
You might want to consider Boost.Signals, which supports implicit disconnect on destruction. For more control over implicit disconnect, consider thread_safe_signals, which I believe is in the vault.

Nat Goodspeed wrote:
Simon Pickles wrote:
I am using boost::functions to provide a simple event system, but have come across a problem.
You might want to consider Boost.Signals, which supports implicit disconnect on destruction. I've heard bad things about the speed of boost signals......

Simon Pickles wrote:
Nat Goodspeed wrote:
You might want to consider Boost.Signals, which supports implicit disconnect on destruction.
I've heard bad things about the speed of boost signals......
? Depends on your application, I suppose. I've heard bad things about the speed of C++ vs. hand-coded assembler. But there are very few situations any more in which I'd willingly choose the latter. We used Boost.Signals as the central event system for an interactive game. Mouse movements, UI controls, internal notifications, frame updates, all used that event system. It was fine for our purposes. Beware of premature optimization.

Nat Goodspeed a écrit :
We used Boost.Signals as the central event system for an interactive game. Mouse movements, UI controls, internal notifications, frame updates, all used that event system. It was fine for our purposes.
I used Boost:signals in a real-time driven simulation applciation, it was fine too.
Beware of premature optimization. And of unfounded urban legend. The whole "C++ is hugely slow" is really, really unwarranted nowadays
-- Joel FALCOU Research Engineer @ Institut d'Electronique Fondamentale Université PARIS SUD XI France

Nat Goodspeed wrote:
Simon Pickles wrote:
Nat Goodspeed wrote:
You might want to consider Boost.Signals, which supports implicit disconnect on destruction.
I've heard bad things about the speed of boost signals......
? Depends on your application, I suppose. I've heard bad things about the speed of C++ vs. hand-coded assembler. But there are very few situations any more in which I'd willingly choose the latter.
We used Boost.Signals as the central event system for an interactive game. Mouse movements, UI controls, internal notifications, frame updates, all used that event system. It was fine for our purposes. Good to hear, thanks
Beware of premature optimization. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (4)
-
Joel FALCOU
-
Nat Goodspeed
-
Simon Pickles
-
Stuart Dootson