Timmo Stange wrote:
Frank Mori Hess wrote:
One solution is to overload the signal::connect function with another version that accepts an additional weak_ptr<void> argument, which points to the object whose member function is being used as a slot. [...] Both problems can be solved, of course, so please just see this as a reminder. The overall solution looks good.
I've thought a little more about it: The original trackable solution isn't a real beauty by itself as it is intrusive to entities which it actually tries to treat as "unaware participants" from the functionality perspective. The trackable objects shouldn't need to know that their lifetime is being monitored by the connection. Your shared_ptr approach supports that notion much better in my opinion, but I would prefer to keep it related to the connection and not the signal and have most of the original flexibility in there. How about using a tool like the function argument reference wrappers to mark the tracked objects? The example for automatic connection management would then look like this: struct NewsMessageArea : public MessageArea { public: // ... void displayNews(const NewsItem& news) const { messageText = news.text(); update(); } }; // ... boost::shared_ptr<NewsMessageArea> newsMessageArea(new NewsMessageArea(/* ... */)); // ... deliverNews.connect(boost::bind(&NewsMessageArea::displayNews, boost::signals::track(newsMessageArea), _1)); The wrapper signals::track would expect a shared_ptr and transport a weak_ptr. The information could be collected with visit_each just like it is done now and the number of trackable objects would only be limited by boost::bind. I think it is acceptable that the client code must maintain a shared_ptr to the tracked instance, as that's expressing rather well what is happening here (even though it doesn't really share the ownership, it shares information about the object).
Patch attached.
Um, looks like I got it wrong. Fixed version attached. Regards Timmo Stange 46,47c46,62 < virtual void disconnect() = 0; < virtual bool connected() const = 0; ---
void disconnect() { boost::mutex::scoped_lock lock(mutex); do_disconnect(); } bool connected() const { boost::mutex::scoped_lock lock(mutex); do_connected(); }
private: virtual void do_disconnect() = 0; virtual bool do_connected() const = 0;
// mutex should be locked when slot is called, to prevent race with disconnect() mutable boost::mutex mutex;
58c73,75 < virtual void disconnect() ---
private: virtual void do_disconnect()
60d76 < boost::mutex::scoped_lock lock(mutex); 63c79 < virtual bool connected() const ---
virtual bool do_connected() const
65d80 < boost::mutex::scoped_lock lock(mutex); 68d82 < // mutex should be locked when slot is called, to prevent race with disconnect() 70d83 < mutable boost::mutex mutex;