Javascript is single-threaded, but can support cooperative multithreading using async/await and promises.
Spidermonkey exposes bindings to allow running promises (code that currently tries to use Promises will crash).
This diff implements the necessary logic to support that, which is mostly two things:
- A JSContext* hook to dispatch promise queuing.
- Logic to run the dispatched jobs (aka the 'event loop').
However, doing that only allows asynchronous JS calls, which is not terribly useful by itself because everything remains single-threaded.
This diff also implements a simple interface to let JS wait on C++ threaded tasks, using the thread pool manager.
The logic is barebones and should perhaps be expended, but works. I've added fairly simple tests covering the above.
One particular inefficiency is that we iterate futures when calling RunJob, which could be inefficient if there are lots of pending futures.
Some notes:
- RunJobs() should be run manually in any context that supports Promises - It's probably a good idea to fail queuing jobs if the scriptinterface isn't supposed to run jobs
- The futures are passed to the script interface so that it knows to wait/cancel them when being destroyed. This looks a lot like Spidermonkey's OffThreadPromiseTask but they kind of assume JSContext lifetime. I think doing it manually is better.
WIP:
- I think the code should be moved from ScriptInterface to a 'ScriptTasks' class somewhere, probably still owned by the scriptInterface.
Future work:
- It would be nice to be able to run JS work in a thread manner, but that's more work.
This demonstrates a very simple one that calls the resolve job instantly when the asynchronous task ends.
Design questions:
- Is it a good idea to support asynchronous calls from Javascript? It might well lead to unpredictable lag.
- If so, when and where?