Reputation: 312
I am currently playing aroung with signals/slots and try to write my own little lib for a micro controller. In this context I had an error, where when I passed an object (context) and a member function as the slot function, the slot was still called despite the object being dead.
Consider the following example:
#include <boost/signals2.hpp>
#include <iostream>
struct A
{
void does() {
std::cout << "i: " << i << " addr: " << (uint64_t)&*this << std::endl;
}
int i = 0;
};
int main()
{
boost::signals2::signal<void()> sig;
{
A a;
std::cout << "addr: " << (uint64_t)&a << std::endl;
sig.connect( [&a]{a.does();});
sig();
}
{
A a;
a.i = 3;
}
sig();
}
output:
addr: 140722327054036
i: 0 addr: 140722327054036
i: 0 addr: 140722327054036
First cout is normal. Second one emitted through the signal is also okay. But the third is pretty strange. For me since the first a
died and I create the second one with i = 3
normally it should print 3
in the second signal since the stack variable should be fully overwritten.
This is btw the same problem I want to achieve in my lib. I want to keep track of references. But I think this is not possible, without inducing some kind of signal inside the destructor probably.
So what would be a good approach to solve that problem? Only thing I can think of is Pub/Sub pattern. This feeld like mostly the same. But I kinda don't like the fact, that each class which can catch a signal has to be derived by a Subscriber class.
Upvotes: 2
Views: 549
Reputation: 393114
You can use a scoped connection to manage the life time of a connection.
scoped_connection keep = sig.connect([&a] { a.does(); });
See Live On Coliru
#include <boost/signals2.hpp>
#include <iostream>
namespace bs = boost::signals2;
static inline int genid() { static int s_current = 0; return ++s_current; }
struct A {
int i = genid();
void operator()() const { std::cout << "i: " << i << std::endl; }
};
int main() {
bs::signal<void()> sig;
{
A a;
bs::scoped_connection keep = sig.connect(a);
sig();
}
{
A a[100] = {};
}
sig();
}
Just prints
i: 1
Upvotes: 1