Page MenuHomeFeedback Tracker

Introduce "ExtensionReady" Event Handler to work with callExtension
Reviewed, WishlistPublic


I have briefly touched on that in this ticket but would like to bring this up as a separate issue.

At the moment it works like this:

callExtension -> RVExtension -> callExtension in one swoop.

For a smooth operation RVExtension has to return immediately. But if extension is made to do something meaningful, RVExtension usually takes time and so the only way to deal with this effectively is to start a worker thread inside dll and return immediately. Then create a sqf loop that would call extension until the result is ready to be collected.

Instead if there was another interface added to dll, RVExtensionCallback for example, that would trigger Event Handler "ExtensionReady", that would have removed the awkwardness of dealing with threaded extensions.

Any data sent to RVExtensionCallback would trigger the code attached to "ExtensionReady" event handler.

addMissionEventHandler ["ExtensionReady", {hint _this}]

_this would be string, just like the one you get back from using callExtension command.


Legacy ID
Feature Request
Steps To Reproduce


Event Timeline

Killzone_Kid edited Additional Information. (Show Details)
Killzone_Kid set Category to Feature Request.
Killzone_Kid set Reproducibility to Always.
Killzone_Kid set Severity to None.
Killzone_Kid set Resolution to Open.
Killzone_Kid set Legacy ID to 1443687291.May 7 2016, 6:36 PM

This is related to #17943 - nearly duplicate except this issue deals with one very specific implementation suggestion without many of the pitfalls I mentioned in a note there.


Even with all of the below resolved, I'd like to point out the nature of this proposal:
It's about moving complexity away from the extension (worker threads) to sqf (continuations).
Away from where a few 'highly skilled wizards' (relatively speaking) have tools and languages that help deal with complexity,
to where the majority of users (sqf scripters often with no "real" programming experience) appear to be struggling with things like code structure as it is.


There are some deeper questions that need answering.

  • If several calls are made to the same extension, should they be queued up until the extension returns or should they be launched in parallel?

The latter would require that the functions are reentrant, and if the extension will "do something meaningful" it also has cross-call resources that need properly synchronized access.
In no case would it be appropriate to put all extensions in the same queue.

  • How will you handle multiple extensions being called?

Analogous to putting them all in the same queue; you cannot suspend calls to one extension (e.g. acre) while waiting for another (a database call).
More importantly, how do you recognize which extension sent a return value back to you?
Two options OTOH:
addMissionEventHandler ["ExtensionReady_MyExtension", {hint _this}];
or making _this an array of ["extensionname","string"]

  • How will you know if the return value is meant for you?

Imagine that when a player joins, you do a database check to get the data for that user.
Now two players joined at nearly the same time. You just got an answer back. Which object do you apply it to?
If we assume the queue above, you could track this manually in a sort of parallel queue, but it would be a chore and it would be error prone.
Another solution is to expand on the above: make _this ["extensionname",something,"output"] as a result of
"extensionname" callextensioncb [something,"input"];

  • Performance? Return value latency?

At what times can the EH fire? I'm going to assume this will be checked at most once per frame.
Will a new thread be created for every request?
Will this be the game handling a "worker thread" for the extension instead of the extension writer?

  • Backward compatibility

Can be achieved in two ways. Overloading on right side being string vs array, or a new command like callextensioncb.


"Then create a sqf loop that would call extension until the result is ready to be collected."
Actually, you could do it all as
_ret = call compile ("ext" callextension "input")
and let the returned "reference" be the code for that loop, with the reference number embedded.
Again, moving the complexity about to where we have better tools for dealing with it.

some valid points here ^^^

multiextension/multiuser I see it this way. Upon extension call, id is returned on submission. this id is then also passed back with result in _this array in extensionReady event handler.