From c8a99e52fc9917d5fa145c32782fa7a7b33b585e Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Tue, 25 Nov 2014 11:34:18 -0500 Subject: Add mono internal API support --- .../runtime/compilerservices/AsyncMethodBuilder.cs | 12 +++++++++++ .../system/threading/Tasks/FutureFactory.cs | 22 ++++++++++++-------- .../mscorlib/system/threading/Tasks/Task.cs | 24 ++++++++++------------ .../system/threading/Tasks/TaskScheduler.cs | 8 ++++++++ 4 files changed, 44 insertions(+), 22 deletions(-) diff --git a/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs b/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs index fa6b3d92ca8..5c6833f33e7 100644 --- a/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs +++ b/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs @@ -825,16 +825,28 @@ namespace System.Runtime.CompilerServices // so that they won't "leak" out of the first await. Thread currentThread = Thread.CurrentThread; +#if MONO + ExecutionContext.Switcher ecs = default (ExecutionContext.Switcher); +#else ExecutionContextSwitcher ecs = default(ExecutionContextSwitcher); +#endif RuntimeHelpers.PrepareConstrainedRegions(); try { +#if MONO + currentThread.BranchExecutionContext (out ecs); +#else ExecutionContext.EstablishCopyOnWriteScope(currentThread, false, ref ecs); +#endif stateMachine.MoveNext(); } finally { +#if MONO + currentThread.RestoreExecutionContext (ref ecs); +#else ecs.Undo(currentThread); +#endif } } diff --git a/mcs/class/referencesource/mscorlib/system/threading/Tasks/FutureFactory.cs b/mcs/class/referencesource/mscorlib/system/threading/Tasks/FutureFactory.cs index f1ed794ccce..f17b2462e40 100644 --- a/mcs/class/referencesource/mscorlib/system/threading/Tasks/FutureFactory.cs +++ b/mcs/class/referencesource/mscorlib/system/threading/Tasks/FutureFactory.cs @@ -851,14 +851,15 @@ namespace System.Threading.Tasks // change will likely brake 4.5 behavior so if possible never touch this code again. if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) { + var invoked = new AtomicBoolean (); //This is 4.5 behaviour //if we don't require synchronization, a faster set result path is taken var asyncResult = beginMethod(iar => { - if (!iar.CompletedSynchronously) + if (invoked.TryRelaxedSet ()) FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true); }, state); - if (asyncResult.CompletedSynchronously) + if (asyncResult != null && asyncResult.CompletedSynchronously && invoked.TryRelaxedSet ()) { Contract.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed."); FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization: false); @@ -991,13 +992,14 @@ namespace System.Threading.Tasks // change will likely brake 4.5 behavior so if possible never touch this code again. if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) { + var invoked = new AtomicBoolean (); //if we don't require synchronization, a faster set result path is taken var asyncResult = beginMethod(arg1, iar => { - if (!iar.CompletedSynchronously) + if (invoked.TryRelaxedSet ()) FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true); }, state); - if (asyncResult.CompletedSynchronously) + if (asyncResult != null && asyncResult.CompletedSynchronously && invoked.TryRelaxedSet ()) { Contract.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed."); FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization: false); @@ -1138,13 +1140,14 @@ namespace System.Threading.Tasks // change will likely brake 4.5 behavior so if possible never touch this code again. if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) { + var invoked = new AtomicBoolean (); //if we don't require synchronization, a faster set result path is taken var asyncResult = beginMethod(arg1, arg2, iar => { - if (!iar.CompletedSynchronously) + if (invoked.TryRelaxedSet ()) FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true); }, state); - if (asyncResult.CompletedSynchronously) + if (asyncResult != null && asyncResult.CompletedSynchronously && invoked.TryRelaxedSet ()) { Contract.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed."); FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization: false); @@ -1293,13 +1296,14 @@ namespace System.Threading.Tasks // change will likely brake 4.5 behavior so if possible never touch this code again. if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) { + var invoked = new AtomicBoolean (); //if we don't require synchronization, a faster set result path is taken var asyncResult = beginMethod(arg1, arg2, arg3, iar => { - if (!iar.CompletedSynchronously) + if (invoked.TryRelaxedSet ()) FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true); }, state); - if (asyncResult.CompletedSynchronously) + if (asyncResult != null && asyncResult.CompletedSynchronously && invoked.TryRelaxedSet ()) { Contract.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed."); FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization: false); @@ -1365,7 +1369,7 @@ namespace System.Threading.Tasks // If the IAsyncResult completed asynchronously, completing the promise will be handled by the callback. // If it completed synchronously, we'll handle that here. - if (asyncResult.CompletedSynchronously) + if (asyncResult != null && asyncResult.CompletedSynchronously) { Contract.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed."); promise.Complete(thisRef, endMethod, asyncResult, requiresSynchronization: false); diff --git a/mcs/class/referencesource/mscorlib/system/threading/Tasks/Task.cs b/mcs/class/referencesource/mscorlib/system/threading/Tasks/Task.cs index 888027770ee..75e440fcf3b 100644 --- a/mcs/class/referencesource/mscorlib/system/threading/Tasks/Task.cs +++ b/mcs/class/referencesource/mscorlib/system/threading/Tasks/Task.cs @@ -594,10 +594,10 @@ namespace System.Threading.Tasks ~(TaskCreationOptions.AttachedToParent | TaskCreationOptions.LongRunning | #if !FEATURE_CORECLR || FEATURE_NETCORE - TaskCreationOptions.DenyChildAttach | + TaskCreationOptions.DenyChildAttach | TaskCreationOptions.HideScheduler | #endif - TaskCreationOptions.PreferFairness)) != 0) + TaskCreationOptions.PreferFairness)) != 0) { throw new ArgumentOutOfRangeException("creationOptions"); } @@ -644,9 +644,9 @@ namespace System.Threading.Tasks if (m_parent != null && ((creationOptions & TaskCreationOptions.AttachedToParent) != 0) #if !FEATURE_CORECLR || FEATURE_NETCORE - && ((m_parent.CreationOptions & TaskCreationOptions.DenyChildAttach) == 0) + && ((m_parent.CreationOptions & TaskCreationOptions.DenyChildAttach) == 0) #endif -) + ) { m_parent.AddNewChild(); } @@ -681,13 +681,13 @@ namespace System.Threading.Tasks // If an unstarted task has a valid CancellationToken that gets signalled while the task is still not queued // we need to proactively cancel it, because it may never execute to transition itself. // The only way to accomplish this is to register a callback on the CT. - // We exclude Promise tasks from this, because TaskCompletionSource needs to fully control the inner tasks's lifetime (i.e. not allow external cancellations) + // We exclude Promise tasks from this, because TaskCompletionSource needs to fully control the inner tasks's lifetime (i.e. not allow external cancellations) if ((((InternalTaskOptions)Options & (InternalTaskOptions.QueuedByRuntime | InternalTaskOptions.PromiseTask #if !FEATURE_CORECLR || FEATURE_NETCORE - | InternalTaskOptions.LazyCancellation + | InternalTaskOptions.LazyCancellation #endif -)) == 0)) + )) == 0)) { if (cancellationToken.IsCancellationRequested) { @@ -720,12 +720,12 @@ namespace System.Threading.Tasks { // If we have an exception related to our CancellationToken, then we need to subtract ourselves // from our parent before throwing it. - if ((m_parent != null) && - ((Options & TaskCreationOptions.AttachedToParent) != 0) + if ((m_parent != null) + && ((Options & TaskCreationOptions.AttachedToParent) != 0) #if !FEATURE_CORECLR || FEATURE_NETCORE - && ((m_parent.Options & TaskCreationOptions.DenyChildAttach) == 0) + && ((m_parent.Options & TaskCreationOptions.DenyChildAttach) == 0) #endif -) + ) { m_parent.DisregardChild(); } @@ -6682,8 +6682,6 @@ namespace System.Threading.Tasks #endif return tasks; } - - } // Proxy class for better debugging experience diff --git a/mcs/class/referencesource/mscorlib/system/threading/Tasks/TaskScheduler.cs b/mcs/class/referencesource/mscorlib/system/threading/Tasks/TaskScheduler.cs index 81226e07e9f..7ca0c6f3dd2 100644 --- a/mcs/class/referencesource/mscorlib/system/threading/Tasks/TaskScheduler.cs +++ b/mcs/class/referencesource/mscorlib/system/threading/Tasks/TaskScheduler.cs @@ -341,6 +341,14 @@ namespace System.Threading.Tasks } } + internal static bool IsDefault + { + get + { + return Current == Default; + } + } + /// /// Gets the TaskScheduler /// associated with the currently executing task. -- cgit v1.2.3