Open vi opened 10 months ago
What you want is called async, which Rhai isn't.
Async means being able to suspend operation in the middle, store the context (whatever), and then resume later on.
You can easily do that by running the Engine
in a separate thread though. Due to the popularity of this, I have just coded up an example, which you'll find here: https://github.com/schungx/rhai/blob/master/examples/pause_and_resume.rs
The example does not seem to prevent many paused executions from hogging as many OS threads. Pausing from on_progress
does not seem to be significantly different from pausing from suspend
.
Callbacks / closures seem to work as a makeshift suspension points. But they lead to ugly Rhai source code.
What can be done with a patterns like this:
func1(arg1, |ret1| {
func2(arg2, ret1, |ret2| {
func3(...)
})
})
, so it would look like
ret1 <- func1(arg1);
ret2 <- func2(arg2, ret1);
func3(...)
Can Rhai's "custom syntax" be used for that? Or maybe better to just pre-process source code and just turn A <- B();
s into B(|A| { /* rest of the file/block */ })
?
Well, that's the pitfalls of using raw threads.
Async is invented just to solve your problem. The compiler saves up you calling stack, allowing you to resume later on. What you described is actually "coroutines" which forms the basis of async in modern languages.
Unfortunately Rhai is not intended for async use. If you need it, the you can look into an async scripting engine.
IMHO, it is a very bad idea to do async in scripts (look at the mess called JavaScript). If you intend scripts to be written by non-expert programmers (otherwise why use scripts?) then you don't really want users to hassle with the problem of async.
Rhai is not intended for this usage scenario. You are better advised to split your API into sections with the async barriers in between. If you want to script an entire application in Rhai with an async API, just like JavaScript... then maybe using JavaScript is best for your use case.
In your example, you can separate your API into different functions:
fn on_init() {
print(1);
}
fn on_suspend() {
return 42;
}
fn on_resume(x) {
print(x);
}
fn on_stop() {
print(4);
}
Callbacks / closures seem to work as a makeshift suspension points. But they lead to ugly Rhai source code.
What you described is, again, async.
This is called the CPS (Continuation-Passing Style) of an async call, before the popular async/await
keywords were invented.
JavaScript has massive amounts of CPS code which led to callback-hell.
I want something like this
It should print
1\n2\n3\n4\n
.Is there some example (e.g. using
internals
feature) to attain this?Alternatively, is there something like "call with current continuation" in Rhai, to avoid each suspension point becoming a closure in Rhai code (i.e. callback hell)?