Partially fix HTML5Thread.readMessage(false).

It now works correctly, but it's much slower.
This commit is contained in:
Joseph Cloutier
2022-03-27 13:40:08 -04:00
parent e487de6153
commit f31adb845f
2 changed files with 31 additions and 17 deletions

View File

@@ -19,6 +19,7 @@ import js.html.Worker;
import js.Lib;
import js.lib.Function;
import js.lib.Object;
import js.lib.Promise;
import js.Syntax;
// Same with classes that import lots of other things.
import lime.app.Application;
@@ -101,34 +102,46 @@ class HTML5Thread {
#end
}
/**
Reads a message from the thread queue. Returns `null` if no argument is
available.
#if !macro
private static inline function zeroDelay():Promise<Dynamic>
{
return new Promise<Dynamic>(function(resolve, _):Void
{
js.Lib.global.setTimeout(resolve);
});
}
#end
@param block If true, uses the `await` keyword to wait for the next
message. Requires the calling function to be `async`.
/**
Reads a message from the thread queue. Returns `null` if no message is
available. This may only be called inside an `async` function.
@param block If true, waits for the next message before returning.
@see `lime.system.WorkOutput.JSAsync.async()`
**/
public static macro function readMessage(block:ExprOf<Bool>):Dynamic
{
var blockFalseExpr:Expr = macro @:privateAccess lime._internal.backend.html5.HTML5Thread.__messages.pop();
// `onmessage` events are only received when the main function is
// suspended, so we must insert `await` even if `block` is false.
// TODO: find a more efficient way to read messages.
var zeroDelayExpr:Expr = macro @:privateAccess {
js.Syntax.code("await {0}", lime._internal.backend.html5.HTML5Thread.zeroDelay());
lime._internal.backend.html5.HTML5Thread.__messages.pop();
};
switch (block.expr)
{
case EConst(CIdent("false")):
return blockFalseExpr;
return zeroDelayExpr;
default:
return macro if ($block && @:privateAccess lime._internal.backend.html5.HTML5Thread.__messages.isEmpty())
{
js.Syntax.code("await {0}", new js.lib.Promise(function(resolve, _)
js.Syntax.code("await {0}", new js.lib.Promise(function(resolve, _):Void
{
@:privateAccess lime._internal.backend.html5.HTML5Thread.__resolveMethods.add(resolve);
}
));
}
else
{
$blockFalseExpr;
};
$zeroDelayExpr;
}
}
@@ -186,8 +199,8 @@ class HTML5Thread {
}
/**
Send a message to the thread queue. This message can be read by
listening for the `onMessage` event.
Send a message to the thread queue. This message can be read using
`readMessage()` or by listening for the `onMessage` event.
@param preserveClasses Whether to call `preserveClasses()` first.
**/

View File

@@ -225,12 +225,13 @@ class WorkOutput
All work will be done on a background thread.
Unlike single-threaded mode, there is no risk of causing lag spikes.
Even so, `doWork` should return at regular intervals, storing its
progress in `state`. This will make it easier to cancel the thread. If
not canceled, `doWork` will be called again immediately.
Even so, `doWork` should return periodically, to allow canceling the
thread. If not canceled, `doWork` will be called again immediately.
In HTML5, web workers will be used to achieve this. This means `doWork`
must be a static function, and you can't use `bind()`.
must be a static function, and you can't use `bind()`. Web workers also
impose a longer delay each time `doWork` returns, so it shouldn't return
as often in multi-threaded mode as in single-threaded mode.
**/
var MULTI_THREADED = true;
}