|
Boost : |
Subject: Re: [boost] Interest in non-intrusive signal/slot lib?
From: Edward Diener (eldiener_at_[hidden])
Date: 2015-05-18 11:42:43
On 5/18/2015 12:35 AM, Emil Dotchevski wrote:
> On Sun, May 17, 2015 at 7:40 PM, Gavin Lambert <gavinl_at_[hidden]>
> wrote:
>
>> On 17/05/2015 09:35, Edward Diener wrote:
>>
>>> typedef void (*button_down)(int x, int y);
>>> typedef void (*button_up)(int x, int y);
>>>
>>> void handle_button_down( int x, int y );
>>> void handle_button_up( int x, int y );
>>>
>>> auto c1=connect<button_down>(e,&handle_button_down);
>>> auto c2=connect<button_up>(e,&handle_button_up);
>>>
>>> Is there some reason why the above would not work ? The fact that
>>> button_down and button_up are the same types above but different types
>>> the way synapse is currently designed seems irrelevant. I am enquiring
>>> whether there is an internal reason for that.
>>>
>>
>> I had the same confusion at first. The issue is that there is no "signal
>> container" instance within the emitter itself, which is how you'd normally
>> distinguish between signals with the same signature.
>>
>> This library stores all signals centrally in the management object,
>> indexed by type, rather than having members of the emitter object (that's
>> the "non-intrusive" part). As a result the types need to be unique as
>> they're the only differentiating feature.
>>
>
> I now understand where the confusion comes from, too. In Boost Signals 2, a
> signal (emitter) is an actual object, and it is the address of that object
> that identifies different signals independently from their signature.
> Indeed, in Synapse signals are *not* objects, they're types.
That's not where the confusion existed for me. Gavin Lambert explained
why each signal must be a different type. I realized that a signal is a
type, but not why the same signal could not be used for more than one
event ( button down, button up etc. ).
BTW you could provide a fairly simple variadic macro for creating
signals which might be a little easier on the end-user:
#define SYNAPSE_SIGNAL(name,...) typedef struct name ## _
(*name)(__VA_ARGS__);
In your documentation I think you should explain that when you emit a
signal you pass a pointer to the object doing the emitting. Also when
you connect you are passing a shared_ptr ( or weak_ptr ) to the object
doing the emitting. I think I have this correct.
Finally i mentioned this before but you did not reply. Is the connected
object designated as a std::function or a boost::function ? I am
guessing the former unless you have overloaded for both.
On the 'connect' page your code overruns the edge of the page.
>
>
>> I am curious whether alternate designs have been considered, such as using
>> strings to locate signals (as in Gtk) or using arbitrary atoms returned
>> from a registration function.
>>
>
> The reason why I've settled on using types is that this way the connections
> are separated "by signal" at compile time, e.g. adding button_down
> connections does not add to the time it takes to emit button_up signals.
>
>
>> I'm also curious if there are any performance consequences of, say,
>> registering a "click" event on hundreds of buttons simultaneously, with
>> different actions required for each, since this model will have a single
>> list with hundreds of entries to search through on each emit, whereas more
>> "traditional" designs will have hundreds of single-entry lists and a much
>> more trivial emit.
>>
>
> The current implementation uses a single list per signal type, meaning that
> if there are multiple emitters emitting the same signal they will
> contribute to the time it takes to emit the signal from a specific emitter.
> In my experience so far this has never showed up in profiling. It is of
> course possible to order by emitter (weak_ptr<void const>::op<) but at this
> point this would be premature.
>
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk