Dimfred
Dimfred

Reputation: 312

boost::signals2 still emits signals to an object where the reference died

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

Answers (1)

sehe
sehe

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

Related Questions