Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
pavelsavara committed Jun 12, 2023
1 parent 6c3a197 commit 7b78063
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ public class Task : IAsyncResult, IDisposable
private int StateFlagsForDebugger => m_stateFlags; // Private property used by a debugger to access this Task's state flags
private TaskStateFlags StateFlags => (TaskStateFlags)(m_stateFlags & ~(int)TaskStateFlags.OptionsMask); // Private property used to help with debugging

#if FEATURE_WASM_THREADS
private static Type? s_jsSynchronizationContextType;
#endif

[Flags]
internal enum TaskStateFlags
{
Expand Down Expand Up @@ -2515,6 +2519,14 @@ internal void SetContinuationForAwait(
goto HaveTaskContinuation;
}
}
#if FEATURE_WASM_THREADS
// when JSSynchronizationContext is installed, we use it regardless of continueOnCapturedContext
else if (SynchronizationContext.Current is SynchronizationContext syncCtx && syncCtx.GetType() == s_jsSynchronizationContextType)
{
tc = new SynchronizationContextAwaitTaskContinuation(syncCtx, continuationAction, flowExecutionContext);
goto HaveTaskContinuation;
}
#endif

if (flowExecutionContext)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ public static void InstallSynchronizationContext (JSMarshalerArgument* arguments
ref JSMarshalerArgument arg_exc = ref arguments_buffer[0]; // initialized by caller in alloc_stack_frame()
try
{
JSHostImplementation.InstallWebWorkerInterop(true);
JSHostImplementation.InstallWebWorkerInterop(true, true);
}
catch (Exception ex)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,12 @@ public static JSObject CreateCSOwnedProxy(nint jsHandle)
}

#if FEATURE_WASM_THREADS
public static void InstallWebWorkerInterop(bool installJSSynchronizationContext)
public static void InstallWebWorkerInterop(bool installJSSynchronizationContext, bool isMainThread)
{
if (isMainThread)
{
SetJSSynchronizationContextType();
}
Interop.Runtime.InstallWebWorkerInterop(installJSSynchronizationContext);
if (installJSSynchronizationContext)
{
Expand Down Expand Up @@ -236,6 +240,7 @@ public static void UninstallWebWorkerInterop()

private static FieldInfo? thread_id_Field;
private static FieldInfo? external_eventloop_Field;
private static FieldInfo? task_s_jsSynchronizationContextType_Field;

// FIXME: after https://github.com/dotnet/runtime/issues/86040 replace with
// [UnsafeAccessor(UnsafeAccessorKind.Field, Name="external_eventloop")]
Expand All @@ -261,6 +266,16 @@ public static IntPtr GetNativeThreadId()
return (int)(long)thread_id_Field.GetValue(Thread.CurrentThread)!;
}

[DynamicDependency(DynamicallyAccessedMemberTypes.NonPublicFields, "System.Threading.Tasks.Task", "System.Private.CoreLib")]
public static void SetJSSynchronizationContextType()
{
if (task_s_jsSynchronizationContextType_Field == null)
{
task_s_jsSynchronizationContextType_Field = typeof(Task).GetField("s_jsSynchronizationContextType", BindingFlags.NonPublic | BindingFlags.Static)!;
}
task_s_jsSynchronizationContextType_Field.SetValue(null, typeof(JSSynchronizationContext));
}

#endif

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public static Task<T> RunAsync<T>(Func<Task<T>> body, CancellationToken cancella
return;
}

JSHostImplementation.InstallWebWorkerInterop(true);
JSHostImplementation.InstallWebWorkerInterop(true, false);
var childScheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task<T> res = body();
// This code is exiting thread main() before all promises are resolved.
Expand Down Expand Up @@ -68,7 +68,7 @@ public static Task RunAsyncVoid(Func<Task> body, CancellationToken cancellationT
return;
}

JSHostImplementation.InstallWebWorkerInterop(true);
JSHostImplementation.InstallWebWorkerInterop(true, false);
var childScheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task res = body();
// This code is exiting thread main() before all promises are resolved.
Expand Down Expand Up @@ -105,7 +105,7 @@ public static Task Run(Action body, CancellationToken cancellationToken)
return;
}

JSHostImplementation.InstallWebWorkerInterop(false);
JSHostImplementation.InstallWebWorkerInterop(false, false);
try
{
body();
Expand Down
2 changes: 1 addition & 1 deletion src/mono/sample/wasm/browser-threads-minimal/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ public static async Task<string> FetchBackground(string url)
Console.WriteLine($"smoke: FetchBackground 2 ManagedThreadId:{Thread.CurrentThread.ManagedThreadId}, SynchronizationContext: {SynchronizationContext.Current?.GetType().FullName ?? "null"}");
var x=JSHost.ImportAsync(fetchhelper, "./fetchhelper.js");
Console.WriteLine($"smoke: FetchBackground 3A ManagedThreadId:{Thread.CurrentThread.ManagedThreadId}, SynchronizationContext: {SynchronizationContext.Current?.GetType().FullName ?? "null"}");
using var import = await x;
using var import = await x.ConfigureAwait(false);
Console.WriteLine($"smoke: FetchBackground 3B ManagedThreadId:{Thread.CurrentThread.ManagedThreadId}, SynchronizationContext: {SynchronizationContext.Current?.GetType().FullName ?? "null"}");
var r = await GlobalThisFetch(url);
Console.WriteLine($"smoke: FetchBackground 4 ManagedThreadId:{Thread.CurrentThread.ManagedThreadId}, SynchronizationContext: {SynchronizationContext.Current?.GetType().FullName ?? "null"}");
Expand Down

0 comments on commit 7b78063

Please sign in to comment.