MultiCast Events: extend invocation code ?

Issue #52 resolved
Arioch The created an issue

I want to add some plumbing around the calls to Invoke(xxx,yyy)

For example turning on/off "wait" crusor.
For example, logging and/or profiling...

For what i can see, i need to hijack

// Spring.Events
procedure TEvent.InternalInvoke(Params: Pointer; StackSize: Integer);
var
  handler: TMethod;
begin
  if Enabled then
    for handler in Handlers do
      InvokeMethod(handler, Params, StackSize);
end;

like

procedure TMyEvent<T>.InternalInvoke(Params: Pointer; StackSize: Integer); override;
begin
   WaitOn();
   try
      inherited;
   finally
      WaitOff();
    end;
end;

But that means it should be protected and virtual. What do you think ?

Also, if it is possible, for logging purposes would be nice if the parameters could be obtained as TArray<TValue> (yes, that is dangerous for destroying refcounted parameters, but so is multi-cast per se)

PS. i think IMulticastNotifyEvent = IEvent<TNotifyEvent>; is to be moved from Spring.Events into root Spring unit, as IEvent<T> is declared right there and the mere use of that type hardly is enought to justify including the implementation-specific unit, as you seem to keep declaration and implementation mostly separated (except for records-based EVENT<T> type)

PPS. we have IMulticastNotifyEvent and we have TMulticastNotifyEvent, perhaps for the sake of completeness we'd have also record-based rMulticastNotifyEvent = Event<TNotifyEvent> ?

Comments (13)

  1. Stefan Glienke repo owner

    The signature of the method is as it is because the RTTI does not provide a way to easily create that stub code for a TRttiMethodType. That is also the reason why the generic event type is not supported in the nextgen compiler. Also the implementation as it is is way faster than it could be with stuffing things into TValue for the super rare case that someone wants to look at the arguments inside the event. That is also why it is private because this is an implementation detail that might change in the future.

    The only possible way I can think of would be virtual Before/After Invoke methods getting called that you can override. But they had to be parameterless aswell to not leak implementation detail about the argument passing. That would then solve your cursor thing. However the use this brings does not justify any changes imo.

    If you have a limited count of event signatures you are using you can look at Spring.Collections.Events how to write some handcrafted version where you can modify the Invoke method to your needs.

    As for the types in Spring.Events.pas that - that will not work for TMulticastNotifyEvent as then Spring.pas would then require Spring.Events to be used in the interface causing a circular reference.

  2. Arioch The reporter

    i do not suggest to change the signature, just the visibility and adress storage convention ( VMT )

    after i did those changes in XE2 Win32/Win6 4 tests pased and Win32 app works too.

    Before/After might work too, but won't it be extra execution time, when in 99% it would not be needed ?

    If anything, keeping it in one method has the benefits of impicit try-finally in ref-counted types as local vars (dynarrays, interfaces, etc) I used temporary hour glass via call to funciton, returning an object via IInterface (into an invisible temp var).

    so i agree the before/after events are not justified, but virtual protected InternalInvoke works like a charm and only if the user would bother to make his class for it

    regarding recovering the parameters, as i told, if it can/should be done, there should be a method reconstructing them from memory dump and returning - if the method is ever called TArray<TValue> - but i aint sure anyone would need it. Just speculating.

    ....

    But I did not suggested moving TmulticastNotify, only Imulticastnotify ! IEvent<T> and TEvent<T> anyway declared in different units, so why not to be consistent with ?Event<TNotifyEvent>

  3. Stefan Glienke repo owner

    The InternalInvoke and InternalInvokeMethod/InternalInvokeDelegate methods are now protected virtual.

    Override them at your own risk.

  4. Log in to comment