
On Sun, Dec 4, 2016 at 10:25 PM, Gavin Lambert
Instance-based signals like you're talking about are what Signals2 does. It has the benefit of callbacks being stored locally, at the cost of being intrusive (the object raising the signal needs to contain the signal instance).
This library takes the other approach of being non-intrusive and storing the signal implementations elsewhere -- the benefit is that you can have objects emit signals on behalf of other objects that don't need to know that the signalling framework exists, but comes with some performance costs as a result.
Some use cases would naturally lend itself to one, while others would lend itself to the other. If all of the code is controlled by you then using Signals2 probably makes more sense, since it's trivial to include the signals in your own classes and it gives you better performance (in theory -- YMMV with mutexes).
But Klemens is asserting that there are some cases where the alternate design is more useful; while I can't think of any such cases I've personally encountered, I have little doubt that they could exist and as such a library that supports it could be useful.
I think what confused me about the Synapse documentation was the use of the term "emitter," which suggests a locally-stored signal instance. The reason I asked earlier about a thread-local map keyed by void* was that understanding that (possible) implementation cleared up the conceptual model for me. In one of our applications, we use an "event" framework in which senders and receivers are loosely coupled. Any given sender and receiver can communicate, regardless of the relative order in which they are constructed, by consulting a central map with find-or-create semantics. They need only agree on the map key. In other words, I believe that application has use cases of the kind that Synapse intends to address. (But the connection need only be made once for each receiver -- the search isn't performed all over again on every event. I expect the same is true for proper use of Synapse.) So for me the term "rendezvous point" makes more sense than "emitter." To me the Synapse library looks like this: * front-end API based on a central map of rendezvous points * back-end implementation of rendezvous points that essentially duplicates Boost.Signals2, with some features omitted (as in the critiques earlier in this thread) Our map's mapped_type is (a thin class wrapped around) boost::signals2::signal. So while I understand the value of having a central map of rendezvous points, I do not understand why you would use anything other than Boost.Signals2 on the back end. It may be that I missed a really good reason in the discussion above. But if it's there, I did miss it. Until I understand that really good reason, I'm not keen on introducing a whole new back-end signals implementation into Boost.