- edited description
MultiCast Events: extend invocation code ?
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)
-
reporter -
reporter - edited description
-
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.
-
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>
-
reporter - attached HourGlassSample.7z
use sample with virtual invoke - can be added to lib code samples, perhaps
works like a charm in xe2 win32/win64
-
repo owner - changed milestone to Future version
-
repo owner - changed version to 1.1
-
repo owner - changed version to 1.1 (released)
-
repo owner - changed version to 1.1 (master)
-
repo owner - changed version to 1.1
-
repo owner - changed milestone to 1.2
- changed component to Base
-
assigned issue to
-
repo owner - changed status to resolved
The InternalInvoke and InternalInvokeMethod/InternalInvokeDelegate methods are now protected virtual.
Override them at your own risk.
-
reporter Thanks. Perhaps you would add a sample to it, just like i oulined above.
- Log in to comment