-
Notifications
You must be signed in to change notification settings - Fork 5.2k
[mono] add internal WebWorkerEventLoop utility class #84492
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
lambdageek
merged 5 commits into
dotnet:main
from
lambdageek:pieces-wasm-threadpool-worker-3-eventloop-util
Apr 20, 2023
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
84fb611
[mono] add internal WebWorkerEventLoop utility class
lambdageek 9b8297f
Use a per-thread unsettled promise count
lambdageek fb3f7ab
remove old emscripten keepalive workaround hack
lambdageek 8f23379
Add a more general getter for JS interop to keep a webworker alive
lambdageek c0c1eed
fixup docs
lambdageek File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
98 changes: 98 additions & 0 deletions
98
...no/System.Private.CoreLib/src/System/Threading/WebWorkerEventLoop.Browser.Threads.Mono.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| using System.Diagnostics.CodeAnalysis; | ||
| using System.Diagnostics.Tracing; | ||
| using System.Runtime.CompilerServices; | ||
|
|
||
| namespace System.Threading; | ||
|
|
||
| /// <summary> | ||
| /// Keep a pthread alive in its WebWorker after its pthread start function returns. | ||
| /// </summary> | ||
| internal static class WebWorkerEventLoop | ||
| { | ||
| // FIXME: these keepalive calls could be qcalls with a SuppressGCTransitionAttribute | ||
| [MethodImpl(MethodImplOptions.InternalCall)] | ||
| private static extern void KeepalivePushInternal(); | ||
| [MethodImpl(MethodImplOptions.InternalCall)] | ||
| private static extern void KeepalivePopInternal(); | ||
|
|
||
| /// <summary> | ||
| /// A keepalive token prevents a thread from shutting down even if it returns to the JS event | ||
| /// loop. A thread may want a keepalive token if it needs to allow JS code to run to settle JS | ||
| /// promises or execute JS timeout callbacks. | ||
| /// </summary> | ||
| internal sealed class KeepaliveToken | ||
| { | ||
| public bool Valid {get; private set; } | ||
|
|
||
| private KeepaliveToken() { Valid = true; } | ||
|
|
||
| /// <summary> | ||
| /// Decrement the Emscripten keepalive count. A thread with a zero keepalive count will | ||
| /// terminate when it returns from its start function or from an async invocation from the | ||
| /// JS event loop. | ||
| /// </summary> | ||
| internal void Pop() { | ||
| if (!Valid) | ||
| throw new InvalidOperationException(); | ||
| Valid = false; | ||
| KeepalivePopInternal(); | ||
| } | ||
|
|
||
| internal static KeepaliveToken Create() | ||
| { | ||
| KeepalivePushInternal(); | ||
| return new KeepaliveToken(); | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Increment the Emscripten keepalive count. A thread with a positive keepalive can return from its | ||
| /// thread start function or a JS event loop invocation and continue running in the JS event | ||
| /// loop. | ||
| /// </summary> | ||
| internal static KeepaliveToken KeepalivePush() => KeepaliveToken.Create(); | ||
|
|
||
| /// <summary> | ||
| /// Start a thread that may be kept alive on its webworker after the start function returns, | ||
| /// if the emscripten keepalive count is positive. Once the thread returns to the JS event | ||
| /// loop it will be able to settle JS promises as well as run any queued managed async | ||
| /// callbacks. | ||
| /// </summary> | ||
| internal static void StartExitable(Thread thread, bool captureContext) | ||
| { | ||
| // don't support captureContext == true, for now, since it's | ||
| // not needed by PortableThreadPool.WorkerThread | ||
| if (captureContext) | ||
| throw new InvalidOperationException(); | ||
| // hack: threadpool threads are exitable, and nothing else is. | ||
| // see create_thread() in mono/metadata/threads.c | ||
| if (!thread.IsThreadPoolThread) | ||
| throw new InvalidOperationException(); | ||
| thread.UnsafeStart(); | ||
| } | ||
|
|
||
| /// returns true if the current thread has unsettled JS Interop promises | ||
| private static bool HasUnsettledInteropPromises => HasUnsettledInteropPromisesNative(); | ||
|
|
||
| // FIXME: this could be a qcall with a SuppressGCTransitionAttribute | ||
| [MethodImpl(MethodImplOptions.InternalCall)] | ||
| private static extern bool HasUnsettledInteropPromisesNative(); | ||
|
|
||
| /// <summary>returns true if the current WebWorker has JavaScript objects that depend on the | ||
| /// current managed thread.</summary> | ||
| /// | ||
| /// <remarks>If this returns false, the runtime is allowed to allow the current managed thread | ||
| /// to exit and for the WebWorker to be recycled by Emscripten for another managed | ||
| /// thread.</remarks> | ||
| internal static bool HasJavaScriptInteropDependents | ||
| { | ||
| // | ||
| // FIXME: | ||
| // https://github.com/dotnet/runtime/issues/85052 - unsettled promises are not the only relevant | ||
| // reasons for keeping a worker thread alive. We will need to add other conditions here. | ||
| get => HasUnsettledInteropPromises; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
|
|
||
| let _per_thread_unsettled_promise_count = 0; | ||
|
|
||
| export function addUnsettledPromise() { | ||
| _per_thread_unsettled_promise_count++; | ||
| } | ||
|
|
||
| export function settleUnsettledPromise() { | ||
| _per_thread_unsettled_promise_count--; | ||
| } | ||
|
|
||
| /// Called from the C# threadpool worker loop to find out if there are any | ||
| /// unsettled JS promises that need to keep the worker alive | ||
| export function mono_wasm_eventloop_has_unsettled_interop_promises(): boolean { | ||
| return _per_thread_unsettled_promise_count > 0; | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.