Hi there,
If I connect a signal to a slot (functor or lambda), and the signal is
then run, it calls the slot.
What if the slot now has code that causes the signal to destruct?
Will this "self-destruct" the slot (functor or lambda), by calling
it's destructor BEFORE the slot-call has finished executing??? This
would be a disaster!
But it seems like is is safe.
It seems:
Even if the signal is destructed (from it's own slot-call), the slot
destructor does not yet get called, until the slot-call has finished.
Which would be safe.
(Code example below)
But is this really the case? Is this always safe? (If so: how does
this roughly work?)
Thanks.
/////////////////////////////////////////////////////////////////////
#include <iostream>
#include <string>
#include
#include <functional>
#include <map>
using namespace std;
using FuncSig = void();
class BaseWrapper {
public:
BaseWrapper() { cout << "BaseWrapper() " << ++mm[""] << endl; }
BaseWrapper(const string &n) : name{n} { cout << "BaseWrapper() "
<< name << ' ' << ++mm[name] << endl; }
BaseWrapper(const BaseWrapper &other) : name{other.name} { cout <<
"BaseWrapper(const BaseWrapper &other) " << name << ' ' << ++mm[name]
<< endl; }
virtual ~BaseWrapper() { cout << "~BaseWrapper() " << name << ' ' <<
mm[name]-- << endl; }
private:
static map mm; // static counter
const string name;
};
map BaseWrapper::mm;
class MySig : BaseWrapper, public boost::signals2::signal<FuncSig> {
};
using Sig = MySig; //boost::signals2::signal<FuncSig>;
class A {
public:
A() {}
boost::signals2::connection add_listener(const string &str, const
Sig::slot_type &slot) {
//my_map.emplace(str, Sig{});
auto x = my_map.emplace(std::piecewise_construct,
std::forward_as_tuple(str),
std::forward_as_tuple());
return x.first->second.connect(slot);
}
void remove_listener(const string &str) {
auto it = my_map.find(str);
if (it != my_map.cend()) {
my_map.erase(it);
}
}
void call(const string &str) {
auto it = my_map.find(str);
if (it != my_map.cend()) {
it->second();
}
}
private:
map my_map;
};
class Functor : BaseWrapper {
public:
Functor(A *a_, int x_) : BaseWrapper{"Functor"}, a{a_}, x{x_} {}
void operator()() const {
cout << " this == " << this << endl;
cout << " x == " << x << endl;
a->remove_listener("hello");
cout << " this == " << this << endl;
cout << " x == " << x << endl;
}
private:
A *a;
int x;
};
int main()
{
A a;
{
Functor fun{&a, 4};
a.add_listener("hello", fun);
}
a.call("hello");
std::cout << "end" << endl;
return 0;
}
/////////////////////////////////////////////////////////////////////