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

Move SynchronizationContext to shared partition #22389

Merged
merged 3 commits into from
Feb 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/System.Private.CoreLib/System.Private.CoreLib.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@
<Compile Include="$(BclSourcesRoot)\System\Threading\Interlocked.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\Monitor.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\Overlapped.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\SynchronizationContext.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\SynchronizationContext.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\Thread.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\ThreadPool.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\Timer.CoreCLR.cs" />
Expand Down Expand Up @@ -367,6 +367,9 @@
<Compile Include="$(BclSourcesRoot)\System\Globalization\GlobalizationMode.Windows.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\ClrThreadPoolBoundHandle.Windows.cs" />
</ItemGroup>
<ItemGroup Condition="'$(FeatureAppX)' == 'true'">
<Compile Include="$(BclSourcesRoot)\System\Threading\SynchronizationContext.Uap.cs" />
</ItemGroup>
<ItemGroup>
<!--
These files are also added to CoreLib.Shared.projitems, but they don't show up in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\SendOrPostCallback.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\SpinLock.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\SpinWait.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\SynchronizationContext.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\SynchronizationLockException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\ThreadLocal.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\Tasks\AsyncCausalityTracerConstants.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Thread = Internal.Runtime.Augments.RuntimeThread;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The #if CORERT should not be necessary. Thread is already in the same namespace and it will be resolved to the correct class. The using will just become no-op on CoreCLR.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is for CoreRT which still does not have Thread (AFAIK)

Copy link
Member

@filipnavara filipnavara Feb 4, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant to keep the using and drop the #if around it. Sorry, I wasn't clear about it :)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. I have removed it although there is a mixture of both used across the files

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It has to be there if the main class is not in the System.Threading namespace (eg. AsyncMethodBuilders). I agree it's confusing and I will be happy to address that once the strategy is decided upon (#22032).


namespace System.Threading
{
public partial class SynchronizationContext
{
private bool _requireWaitNotification;

public SynchronizationContext()
{
}

#if !FEATURE_APPX && !ENABLE_WINRT
public static SynchronizationContext Current => Thread.CurrentThread.SynchronizationContext;
#endif

protected void SetWaitNotificationRequired() => _requireWaitNotification = true;

public bool IsWaitNotificationRequired() => _requireWaitNotification;

public virtual void Send(SendOrPostCallback d, object state) => d(state);

public virtual void Post(SendOrPostCallback d, object state) => ThreadPool.QueueUserWorkItem(s => s.d(s.state), (d, state), preferLocal: false);

/// <summary>
/// Optional override for subclasses, for responding to notification that operation is starting.
/// </summary>
public virtual void OperationStarted()
{
}

/// <summary>
/// Optional override for subclasses, for responding to notification that operation has completed.
/// </summary>
public virtual void OperationCompleted()
{
}

[CLSCompliant(false)]
public virtual int Wait(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout)
{
return WaitHelper(waitHandles, waitAll, millisecondsTimeout);
}

[CLSCompliant(false)]
protected static int WaitHelper(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout)
{
if (waitHandles == null)
{
throw new ArgumentNullException(nameof(waitHandles));
}

return WaitHandle.WaitMultipleIgnoringSyncContext(waitHandles, waitAll, millisecondsTimeout);
}

public static void SetSynchronizationContext(SynchronizationContext syncContext) => Thread.CurrentThread.SynchronizationContext = syncContext;

public virtual SynchronizationContext CreateCopy() => new SynchronizationContext();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

namespace System.Threading
{
public partial class SynchronizationContext
{
private static int InvokeWaitMethodHelper(SynchronizationContext syncContext, IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout)
{
return syncContext.Wait(waitHandles, waitAll, millisecondsTimeout);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Reflection;
using System.Diagnostics;

namespace System.Threading
{
public partial class SynchronizationContext
{
public static SynchronizationContext Current
{
get
{
SynchronizationContext context = Thread.CurrentThread.SynchronizationContext;

if (context == null && ApplicationModel.IsUap)
context = GetWinRTContext();

return context;
}
}

private static SynchronizationContext GetWinRTContext()
{
Debug.Assert(Environment.IsWinRTSupported);
Debug.Assert(ApplicationModel.IsUap);

//
// We call into the VM to get the dispatcher. This is because:
//
// a) We cannot call the WinRT APIs directly from mscorlib, because we don't have the fancy projections here.
// b) We cannot call into System.Runtime.WindowsRuntime here, because we don't want to load that assembly
// into processes that don't need it (for performance reasons).
//
// So, we check the VM to see if the current thread has a dispatcher; if it does, we pass that along to
// System.Runtime.WindowsRuntime to get a corresponding SynchronizationContext.
//
object dispatcher = GetWinRTDispatcherForCurrentThread();
if (dispatcher != null)
return GetWinRTSynchronizationContext(dispatcher);

return null;
}

private static Func<object, SynchronizationContext> s_createSynchronizationContextDelegate;

private static SynchronizationContext GetWinRTSynchronizationContext(object dispatcher)
{
//
// Since we can't directly reference System.Runtime.WindowsRuntime from mscorlib, we have to get the factory via reflection.
// It would be better if we could just implement WinRTSynchronizationContextFactory in mscorlib, but we can't, because
// we can do very little with WinRT stuff in mscorlib.
//
Func<object, SynchronizationContext> createSynchronizationContextDelegate = s_createSynchronizationContextDelegate;
if (createSynchronizationContextDelegate == null)
{
Type factoryType = Type.GetType("System.Threading.WinRTSynchronizationContextFactory, System.Runtime.WindowsRuntime", throwOnError: true);

// Create an instance delegate for the Create static method
MethodInfo createMethodInfo = factoryType.GetMethod("Create", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
createSynchronizationContextDelegate = (Func<object, SynchronizationContext>)Delegate.CreateDelegate(typeof(Func<object, SynchronizationContext>), createMethodInfo, /* throwOnBindFailure */ true);

s_createSynchronizationContextDelegate = createSynchronizationContextDelegate;
}

return s_createSynchronizationContextDelegate(dispatcher);
}

[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Interface)]
private static extern object GetWinRTDispatcherForCurrentThread();
}
}
Loading