palacaze / sigslot

A simple C++14 signal-slots implementation

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

sig<>disconnect

pyaggi opened this issue · comments

First of all, great job !
the only thing I'm missing from other implementations (like Qt's or ENTT's) is the possibility
to call disconnect with the same signature as in connect and not to hold an object for every connection (not all my objects are trackable).
Do you think it is possible to add that feature ? even in an outside container used to search for a connection object will be great.
Bests Regards,
Pablo

Thank you for you kind words.

I think that would be doable to add disconnection for either a particular callable type or object instance.
The main limitation I can think of is lambda disconnection, that will not work, or at least it will not be straightforward.

I will look into it. Are there other operations that would benefit from this way of retrieving connections? Connection blocking maybe?

This issue is a year old, but have you been working on this? It's a useful feature.

I had a first look at it yesterday.
The current design does not accommodate well with such a feature, it will be a little tricky to make it work.

@pyaggi @felaugmar, I just pushed support for this feature.

There are 3 overloads that allow disconnection for a particular function signature/callable of any kind, for a pointer to objet/trackable object as well as for a signature + object.

I was able to make it work in every situation but the implementation is not straightforward, I have not taken the time to ensure everything is correctly defined with respect to the standard. Let me know if you see any kind of failure, especially on Windows platform.

Awesome @palacaze this feature will be of great help 😁
I found some errors like: #8 building in MSVC, I fixed them and looks ok.

I can make a pull request with the fixes if you can't.

I pushed a couple of fixes for MSVC, It should be working now.

I figured it would not be so easy.

First, pointers to functions and member functions may have any size, so I can't just hope to get an address as a pointer to object and compare those. I have a fix working locally for this.

But what is more worrying is that pointer to member functions of unrelated classes can't be compared for equality. For instance, virtual functions pointers on GCC seems to be implemented as offsets into the virtual table, So two pointers to member functions of two different classes, but at the same offset, will get the same address.

Here is what I get for the following definitions on GCC 9:

void fun() {}

struct b1 {
    virtual ~b1() = default;
    static void sm() {}
    void m() {}
    virtual void vm() {}
};

struct b2 {
    virtual ~b2() = default;
    static void sm() {}
    void m() {}
    virtual void vm() {}
};

struct c {
    virtual ~c() = default;
    virtual void w() {}
};

struct d : b1 {
    static void sm() {}
    void m() {}
    void vm() override {}
};

struct e : b1, c {
    static void sm() {}
    void m() {}
    void vm() override{}
};
Symbol GCC 9 Linux 64
Sizeof
GCC 9 Linux 64
Address
MSVC 16.6 32
Sizeof
MSVC 16.6 32
Address
GCC 8 Mingw 32
Sizeof
GCC 8 Mingw 32
Address
fun 8 0x802340 4 0x1311A6 4 0xF41540
&b1::sm 8 0xE03140 4 0x7612A5 4 0x308D40
&b1::m 16 0xF03240 4 0x1514A5 8 0x248D40
&b1::vm 16 0x11 4 0x9F11A5 8 0x09
&b2::sm 8 0x003340 4 0xA515A5 4 0x408D40
&b2::m 16 0x103440 4 0xEB10A5 8 0x348D40
&b2::vm 16 0x11 4 0x6A14A5 8 0x09
&d::sm 8 0x203440 4 0x2612A5 4 0x108D40
&d::m 16 0x303540 4 0x9D13A5 8 0x048D40
&d::vm 16 0x11 4 0x4412A5 8 0x09
&e::sm 8 0x403540 4 0xF911A5 4 0x208D40
&e::m 16 0x503640 8 0x8111A5 8 0x148D40
&e::vm 16 0x11 8 0xA911A5 8 0x09

Indeed, &b1::vm, &b2::vm, &d::vm and &e::vm are not distinguishable by address on GCC. Having a signal<>::disconnect(pmf) and only comparing pointer addresses is plain wrong.

I see three possible ways of fixing this problem:

  1. Removing this disconnect() overload,
  2. Using RTTI to compare both the function pointer address and class type,
  3. Using some sort of compile time type information mechanism to perform the same as 2.

I now know why I ignored this issue for a whole year 😄

I will attempt approach 2. for now, then maybe implement a CTTI solution.

The new approach to disconnection I just pushed on the slot_group branch should be correct in all situations. In particular it should work with virtual methods and multiple inheritance.

Should be fixed now.
If all goes well I will tag 1.2 in a few days.