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.