Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 87831b1

Browse files
committed
Move SynchronizationContext to shared partition
1 parent bbd7905 commit 87831b1

File tree

8 files changed

+174
-235
lines changed

8 files changed

+174
-235
lines changed

src/System.Private.CoreLib/System.Private.CoreLib.csproj

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@
268268
<Compile Include="$(BclSourcesRoot)\System\Threading\Interlocked.cs" />
269269
<Compile Include="$(BclSourcesRoot)\System\Threading\Monitor.cs" />
270270
<Compile Include="$(BclSourcesRoot)\System\Threading\Overlapped.cs" />
271-
<Compile Include="$(BclSourcesRoot)\System\Threading\SynchronizationContext.cs" />
271+
<Compile Include="$(BclSourcesRoot)\System\Threading\SynchronizationContext.CoreCLR.cs" />
272272
<Compile Include="$(BclSourcesRoot)\System\Threading\Thread.cs" />
273273
<Compile Include="$(BclSourcesRoot)\System\Threading\ThreadPool.CoreCLR.cs" />
274274
<Compile Include="$(BclSourcesRoot)\System\Threading\Timer.CoreCLR.cs" />
@@ -367,6 +367,9 @@
367367
<Compile Include="$(BclSourcesRoot)\System\Globalization\GlobalizationMode.Windows.cs" />
368368
<Compile Include="$(BclSourcesRoot)\System\Threading\ClrThreadPoolBoundHandle.Windows.cs" />
369369
</ItemGroup>
370+
<ItemGroup Condition="'$(FeatureAppX)' == 'true' or '$(EnableWinRT)' == 'true'">
371+
<Compile Include="$(BclSourcesRoot)\System\Threading\SynchronizationContext.Uap.cs" />
372+
</ItemGroup>
370373
<ItemGroup>
371374
<!--
372375
These files are also added to CoreLib.Shared.projitems, but they don't show up in

src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -788,6 +788,7 @@
788788
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\SendOrPostCallback.cs" />
789789
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\SpinLock.cs" />
790790
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\SpinWait.cs" />
791+
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\SynchronizationContext.cs" />
791792
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\SynchronizationLockException.cs" />
792793
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\ThreadLocal.cs" />
793794
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\Tasks\AsyncCausalityTracerConstants.cs" />
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
#if CORERT
6+
using Thread = Internal.Runtime.Augments.RuntimeThread;
7+
#endif
8+
9+
namespace System.Threading
10+
{
11+
public partial class SynchronizationContext
12+
{
13+
private bool _requireWaitNotification;
14+
15+
public SynchronizationContext()
16+
{
17+
}
18+
19+
#if !FEATURE_APPX
20+
public static SynchronizationContext Current => Thread.CurrentThread.SynchronizationContext;
21+
#endif
22+
23+
protected void SetWaitNotificationRequired() => _requireWaitNotification = true;
24+
25+
public bool IsWaitNotificationRequired() => _requireWaitNotification;
26+
27+
public virtual void Send(SendOrPostCallback d, object state) => d(state);
28+
29+
public virtual void Post(SendOrPostCallback d, object state) => ThreadPool.QueueUserWorkItem(s => s.d(s.state), (d, state), preferLocal: false);
30+
31+
/// <summary>
32+
/// Optional override for subclasses, for responding to notification that operation is starting.
33+
/// </summary>
34+
public virtual void OperationStarted()
35+
{
36+
}
37+
38+
/// <summary>
39+
/// Optional override for subclasses, for responding to notification that operation has completed.
40+
/// </summary>
41+
public virtual void OperationCompleted()
42+
{
43+
}
44+
45+
[CLSCompliant(false)]
46+
public virtual int Wait(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout)
47+
{
48+
return WaitHelper(waitHandles, waitAll, millisecondsTimeout);
49+
}
50+
51+
[CLSCompliant(false)]
52+
protected static int WaitHelper(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout)
53+
{
54+
if (waitHandles == null)
55+
{
56+
throw new ArgumentNullException(nameof(waitHandles));
57+
}
58+
59+
return WaitHelperNative(waitHandles, waitAll, millisecondsTimeout);
60+
}
61+
62+
public static void SetSynchronizationContext(SynchronizationContext syncContext) => Thread.CurrentThread.SynchronizationContext = syncContext;
63+
64+
public virtual SynchronizationContext CreateCopy() => new SynchronizationContext();
65+
}
66+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Runtime.CompilerServices;
6+
7+
namespace System.Threading
8+
{
9+
public partial class SynchronizationContext
10+
{
11+
private static int InvokeWaitMethodHelper(SynchronizationContext syncContext, IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout)
12+
{
13+
return syncContext.Wait(waitHandles, waitAll, millisecondsTimeout);
14+
}
15+
16+
// Static helper to which the above method can delegate to in order to get the default
17+
// COM behavior.
18+
[MethodImplAttribute(MethodImplOptions.InternalCall)]
19+
private static extern int WaitHelperNative(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout);
20+
21+
}
22+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Runtime.InteropServices;
6+
using System.Runtime.CompilerServices;
7+
using System.Reflection;
8+
using System.Diagnostics;
9+
10+
namespace System.Threading
11+
{
12+
public partial class SynchronizationContext
13+
{
14+
public static SynchronizationContext Current
15+
{
16+
get
17+
{
18+
SynchronizationContext context = Thread.CurrentThread.SynchronizationContext;
19+
20+
if (context == null && ApplicationModel.IsUap)
21+
context = GetWinRTContext();
22+
23+
return context;
24+
}
25+
}
26+
27+
private static SynchronizationContext GetWinRTContext()
28+
{
29+
Debug.Assert(Environment.IsWinRTSupported);
30+
Debug.Assert(ApplicationModel.IsUap);
31+
32+
//
33+
// We call into the VM to get the dispatcher. This is because:
34+
//
35+
// a) We cannot call the WinRT APIs directly from mscorlib, because we don't have the fancy projections here.
36+
// b) We cannot call into System.Runtime.WindowsRuntime here, because we don't want to load that assembly
37+
// into processes that don't need it (for performance reasons).
38+
//
39+
// So, we check the VM to see if the current thread has a dispatcher; if it does, we pass that along to
40+
// System.Runtime.WindowsRuntime to get a corresponding SynchronizationContext.
41+
//
42+
object dispatcher = GetWinRTDispatcherForCurrentThread();
43+
if (dispatcher != null)
44+
return GetWinRTSynchronizationContext(dispatcher);
45+
46+
return null;
47+
}
48+
49+
private static Func<object, SynchronizationContext> s_createSynchronizationContextDelegate;
50+
51+
private static SynchronizationContext GetWinRTSynchronizationContext(object dispatcher)
52+
{
53+
//
54+
// Since we can't directly reference System.Runtime.WindowsRuntime from mscorlib, we have to get the factory via reflection.
55+
// It would be better if we could just implement WinRTSynchronizationContextFactory in mscorlib, but we can't, because
56+
// we can do very little with WinRT stuff in mscorlib.
57+
//
58+
Func<object, SynchronizationContext> createSynchronizationContextDelegate = s_createSynchronizationContextDelegate;
59+
if (createSynchronizationContextDelegate == null)
60+
{
61+
Type factoryType = Type.GetType("System.Threading.WinRTSynchronizationContextFactory, System.Runtime.WindowsRuntime", throwOnError: true);
62+
63+
// Create an instance delegate for the Create static method
64+
MethodInfo createMethodInfo = factoryType.GetMethod("Create", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
65+
createSynchronizationContextDelegate = (Func<object, SynchronizationContext>)Delegate.CreateDelegate(typeof(Func<object, SynchronizationContext>), createMethodInfo, /* throwOnBindFailure */ true);
66+
67+
s_createSynchronizationContextDelegate = createSynchronizationContextDelegate;
68+
}
69+
70+
return s_createSynchronizationContextDelegate(dispatcher);
71+
}
72+
73+
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
74+
[return: MarshalAs(UnmanagedType.Interface)]
75+
private static extern object GetWinRTDispatcherForCurrentThread();
76+
}
77+
}

0 commit comments

Comments
 (0)