Opened 10 years ago
Closed 10 years ago
#7724 closed Bugs (invalid)
executing signals2::signal::connect creates many copies of the connected object
Reported by: | Owned by: | Frank Mori Hess | |
---|---|---|---|
Milestone: | To Be Determined | Component: | signals2 |
Version: | Boost 1.49.0 | Severity: | Problem |
Keywords: | signals2 connect multiple objects copy | Cc: |
Description
I am trying to figure out where is the problem, maybe what I have implemented is incorrect or it is a bug.
When trying to connect to a signal the passed object is copied many times and the final triggered signal executes a method on a copy of the passed object.
Signal is the following type:
typedef signals2::signal<void (NotificationCenter::Notification)> Signal;
Following code (NotificationCenter creates a shared_ptr<> to the requested signals):
class NotificationReceived { public: int runCount; NotificationReceived() { std::cout << "* Receiver CREATED" << std::endl; runCount = 0; } NotificationReceived(const NotificationReceived &cSource) { std::cout << "* Receiver COPIED" << std::endl; runCount = cSource.runCount; } ~NotificationReceived() { std::cout << "* Receiver DELETED" << std::endl; } void Receive(NotificationCenter::Notification notif) { std::cout << std::endl << "Receive: Notification received: " + notif.m_information << std::endl << std::endl; runCount++; } }; BOOST_AUTO_TEST_CASE( test_notification_center_notify) { NotificationCenter nCenter(NotificationCenter::NCT_DELAYED); NotificationReceived receiver; NotificationCenter::Signal* sig = nCenter.RegisterForNotification(NotificationCenter::Notification::NT_BROADCAST); sig->connect(boost::bind(&NotificationReceived::Receive, receiver, _1)); nCenter.BroadcastNotification(NotificationCenter::Notification(NotificationCenter::Notification::NT_BROADCAST, "Testing")); boost::this_thread::sleep(boost::posix_time::seconds(2)); BOOST_REQUIRE_EQUAL(receiver.runCount, 1); }
Has following output:
* Receiver CREATED - Queue empty - sleeping 500ms * Receiver COPIED * Receiver COPIED * Receiver COPIED * Receiver COPIED * Receiver COPIED * Receiver DELETED * Receiver DELETED * Receiver DELETED * Receiver COPIED * Receiver DELETED * Receiver DELETED * Receiver COPIED * Receiver COPIED * Receiver COPIED * Receiver COPIED * Receiver COPIED * Receiver COPIED * Receiver COPIED * Receiver COPIED * Receiver DELETED * Receiver DELETED * Receiver DELETED * Receiver DELETED * Receiver DELETED * Receiver DELETED * Receiver COPIED * Receiver DELETED * Receiver COPIED * Receiver DELETED * Receiver DELETED * Receiver COPIED * Receiver DELETED * Receiver DELETED - Thread waked up - Queue not empty, searching receivers ... - Sending notification Receive: Notification received: Testing - Queue empty - sleeping 500ms - Thread waked up - Queue empty - sleeping 500ms - Thread waked up - Queue empty - sleeping 500ms * Receiver DELETED * Receiver DELETED *** 1 failure detected in test suite "FrameworkTests"
Why the "receiver" object has been copied many times and the final method has not been executed on the original object but on a copy which proves the check of the "runCount"?
I have managed to go around this problem adding a shared_ptr<>
Following code (classes the same):
NotificationCenter nCenter(NotificationCenter::NCT_DELAYED); boost::shared_ptr<NotificationReceived> receiver(new NotificationReceived); NotificationCenter::Signal* sig = nCenter.RegisterForNotification(NotificationCenter::Notification::NT_BROADCAST); sig->connect(boost::bind(&NotificationReceived::Receive, receiver, _1)); nCenter.BroadcastNotification(NotificationCenter::Notification(NotificationCenter::Notification::NT_BROADCAST, "Testing")); boost::this_thread::sleep(boost::posix_time::seconds(2)); BOOST_REQUIRE_EQUAL(receiver->runCount, 1);
Outputs what I expected also from the first example:
* Receiver CREATED - Queue empty - sleeping 500ms - Thread waked up - Queue not empty, searching receivers ... - Sending notification Receive: Notification received: Testing - Queue empty - sleeping 500ms - Thread waked up - Queue empty - sleeping 500ms - Thread waked up - Queue empty - sleeping 500ms * Receiver DELETED *** No errors detected
It's not a bug. Slots are copied by value, by design. If you want, you can submit a separate bug regarding the poor documentation of this fact.