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;
import js.lib.Function; import js.lib.Function;
import js.lib.Object; import js.lib.Object;
import js.lib.Promise;
import js.Syntax; import js.Syntax;
// Same with classes that import lots of other things. // Same with classes that import lots of other things.
import lime.app.Application; import lime.app.Application;
@@ -101,34 +102,46 @@ class HTML5Thread {
#end #end
} }
/** #if !macro
Reads a message from the thread queue. Returns `null` if no argument is private static inline function zeroDelay():Promise<Dynamic>
available. {
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()` @see `lime.system.WorkOutput.JSAsync.async()`
**/ **/
public static macro function readMessage(block:ExprOf<Bool>):Dynamic 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) switch (block.expr)
{ {
case EConst(CIdent("false")): case EConst(CIdent("false")):
return blockFalseExpr; return zeroDelayExpr;
default: default:
return macro if ($block && @:privateAccess lime._internal.backend.html5.HTML5Thread.__messages.isEmpty()) 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); @:privateAccess lime._internal.backend.html5.HTML5Thread.__resolveMethods.add(resolve);
} }
)); ));
} }
else else
{ $zeroDelayExpr;
$blockFalseExpr;
};
} }
} }
@@ -186,8 +199,8 @@ class HTML5Thread {
} }
/** /**
Send a message to the thread queue. This message can be read by Send a message to the thread queue. This message can be read using
listening for the `onMessage` event. `readMessage()` or by listening for the `onMessage` event.
@param preserveClasses Whether to call `preserveClasses()` first. @param preserveClasses Whether to call `preserveClasses()` first.
**/ **/

View File

@@ -225,12 +225,13 @@ class WorkOutput
All work will be done on a background thread. All work will be done on a background thread.
Unlike single-threaded mode, there is no risk of causing lag spikes. Unlike single-threaded mode, there is no risk of causing lag spikes.
Even so, `doWork` should return at regular intervals, storing its Even so, `doWork` should return periodically, to allow canceling the
progress in `state`. This will make it easier to cancel the thread. If thread. If not canceled, `doWork` will be called again immediately.
not canceled, `doWork` will be called again immediately.
In HTML5, web workers will be used to achieve this. This means `doWork` 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; var MULTI_THREADED = true;
} }