private static void OnAddressChanged() { Dictionary <NetworkAddressChangedEventHandler, ExecutionContext?>?addressChangedSubscribers = null; lock (s_gate) { if (s_addressChangedSubscribers.Count > 0) { addressChangedSubscribers = new Dictionary <NetworkAddressChangedEventHandler, ExecutionContext?>(s_addressChangedSubscribers); } } if (addressChangedSubscribers != null) { foreach (KeyValuePair <NetworkAddressChangedEventHandler, ExecutionContext?> subscriber in addressChangedSubscribers) { NetworkAddressChangedEventHandler handler = subscriber.Key; ExecutionContext?ec = subscriber.Value; if (ec == null) // Flow supressed { handler(null, EventArgs.Empty); } else { ExecutionContext.Run(ec, s_runAddressChangedHandler, handler); } } } }
public static void Start <TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { if (stateMachine == null) // TStateMachines are generally non-nullable value types, so this check will be elided { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.stateMachine); } Thread currentThread = Thread.CurrentThread; // Store current ExecutionContext and SynchronizationContext as "previousXxx". // This allows us to restore them and undo any Context changes made in stateMachine.MoveNext // so that they won't "leak" out of the first await. ExecutionContext? previousExecutionCtx = currentThread._executionContext; SynchronizationContext?previousSyncCtx = currentThread._synchronizationContext; try { stateMachine.MoveNext(); } finally { // The common case is that these have not changed, so avoid the cost of a write barrier if not needed. if (previousSyncCtx != currentThread._synchronizationContext) { // Restore changed SynchronizationContext back to previous currentThread._synchronizationContext = previousSyncCtx; } ExecutionContext?currentExecutionCtx = currentThread._executionContext; if (previousExecutionCtx != currentExecutionCtx) { ExecutionContext.RestoreChangedContextToThread(currentThread, previousExecutionCtx, currentExecutionCtx); } } }
public CompletionData(Action <object?> completion, object?completionState, ExecutionContext?executionContext, SynchronizationContext?synchronizationContext) { Completion = completion; CompletionState = completionState; ExecutionContext = executionContext; SynchronizationContext = synchronizationContext; }
static async void OnCompletedSlow(ValueTask source, Action <object?> continuation, object?state, ValueTaskSourceOnCompletedFlags flags) { ExecutionContext? execContext = null; SynchronizationContext?syncContext = null; if ((flags & ValueTaskSourceOnCompletedFlags.FlowExecutionContext) == ValueTaskSourceOnCompletedFlags.FlowExecutionContext) { execContext = ExecutionContext.Capture(); } if ((flags & ValueTaskSourceOnCompletedFlags.UseSchedulingContext) == ValueTaskSourceOnCompletedFlags.UseSchedulingContext) { syncContext = SynchronizationContext.Current; } try { await source.ConfigureAwait(false); } catch { } if (execContext != null) { ExecutionContext.Run(execContext, execContextCallback, Tuple.Create(continuation, state, syncContext)); } else if (syncContext != null) { syncContext.Post(syncContextCallback, Tuple.Create(continuation, state, syncContext)); } else { continuation(state); } }
public void OnCompleted(Action <object?> continuation, object?state, ValueTaskSourceOnCompletedFlags flags, out CompletionData completionData, out bool doubleCompletion) { completionData = default; doubleCompletion = !ReferenceEquals(_completion, null); if (IsCompleted || doubleCompletion) { completionData = new CompletionData(continuation, state, _executionContext, _synchronizationContext); return; } _completion = continuation; _completionState = state; // Capture the SynchronizationContext if there's any and we're allowing capture (from pipe options) if ((_awaitableState & AwaitableState.UseSynchronizationContext) != 0 && (flags & ValueTaskSourceOnCompletedFlags.UseSchedulingContext) != 0) { SynchronizationContext?sc = SynchronizationContext.Current; if (sc != null && sc.GetType() != typeof(SynchronizationContext)) { _synchronizationContext = sc; } } // Capture the execution context if ((flags & ValueTaskSourceOnCompletedFlags.FlowExecutionContext) != 0) { _executionContext = ExecutionContext.Capture(); } }
private Authorization?SetContextAndTryAuthenticate(ISmtpAuthenticationModule module, NetworkCredential?credential, ContextAwareResult?context) { // We may need to restore user thread token here if (ReferenceEquals(credential, CredentialCache.DefaultNetworkCredentials)) { #if DEBUG Debug.Assert(context == null || context.IdentityRequested, "Authentication required when it wasn't expected. (Maybe Credentials was changed on another thread?)"); #endif try { ExecutionContext?x = context == null ? null : context.ContextCopy; if (x != null) { AuthenticateCallbackContext authenticationContext = new AuthenticateCallbackContext(this, module, credential, _client !.TargetName, null); ExecutionContext.Run(x, s_AuthenticateCallback, authenticationContext); return(authenticationContext._result); } else { return(module.Authenticate(null, credential, this, _client !.TargetName, null)); } } catch { // Prevent the impersonation from leaking to upstack exception filters. throw; } } return(module.Authenticate(null, credential, this, _client !.TargetName, null)); }
private void MoveNext(Thread?threadPoolThread) { Debug.Assert(!IsCompleted); bool loggingOn = TplEventSource.Log.IsEnabled(); if (loggingOn) { TplEventSource.Log.TraceSynchronousWorkBegin(this.Id, CausalitySynchronousWork.Execution); } ExecutionContext?context = Context; if (context == null) { Debug.Assert(StateMachine != null); StateMachine.MoveNext(); } else { if (threadPoolThread is null) { ExecutionContext.RunInternal(context, s_callback, this); } else { ExecutionContext.RunFromThreadPoolDispatchLoop(threadPoolThread, context, s_callback, this); } } if (IsCompleted) { // If async debugging is enabled, remove the task from tracking. if (System.Threading.Tasks.Task.s_asyncDebuggingEnabled) { System.Threading.Tasks.Task.RemoveFromActiveTasks(this); } // Clear out state now that the async method has completed. // This avoids keeping arbitrary state referenced by lifted locals // if this Task / state machine box is held onto. StateMachine = default; Context = default; #if !CORERT // In case this is a state machine box with a finalizer, suppress its finalization // as it's now complete. We only need the finalizer to run if the box is collected // without having been completed. if (AsyncMethodBuilderCore.TrackAsyncMethodCompletion) { GC.SuppressFinalize(this); } #endif } if (loggingOn) { TplEventSource.Log.TraceSynchronousWorkEnd(CausalitySynchronousWork.Execution); } }
// This method is guaranteed to be called only once. If called with a non-zero userToken, the context is not flowed. protected override void Complete(IntPtr userToken) { if (NetEventSource.Log.IsEnabled()) { NetEventSource.Info(this, $"_context(set):{_context != null} userToken:{userToken}"); } // If no flowing, just complete regularly. if ((_flags & StateFlags.PostBlockStarted) == 0) { base.Complete(userToken); return; } // At this point, IsCompleted is set and CompletedSynchronously is fixed. If it's synchronous, then we want to hold // the completion for the CaptureOrComplete() call to avoid the context flow. If not, we know CaptureOrComplete() has completed. if (CompletedSynchronously) { return; } ExecutionContext?context = _context; // If the context is being abandoned or wasn't captured (SuppressFlow, null AsyncCallback), just // complete regularly, as long as CaptureOrComplete() has finished. // if (userToken != IntPtr.Zero || context == null) { base.Complete(userToken); return; } ExecutionContext.Run(context, s => ((ContextAwareResult)s !).CompleteCallback(), this); }
public void OnCompleted(Action <object?> continuation, object?state, short token, ValueTaskSourceOnCompletedFlags flags) { var c = Interlocked.CompareExchange(ref this.continuation, continuation, ContinuationSentinel.AvailableContinuation); if (c == ContinuationSentinel.CompletedContinuation) { continuation(state); return; } if (c != ContinuationSentinel.AvailableContinuation) { throw new InvalidOperationException("does not allow multiple await."); } if (state == null) { throw new InvalidOperationException("invalid state."); } if ((flags & ValueTaskSourceOnCompletedFlags.FlowExecutionContext) == ValueTaskSourceOnCompletedFlags.FlowExecutionContext) { execContext = ExecutionContext.Capture(); } if ((flags & ValueTaskSourceOnCompletedFlags.UseSchedulingContext) == ValueTaskSourceOnCompletedFlags.UseSchedulingContext) { syncContext = SynchronizationContext.Current; } this.state = state; if (GetStatus(token) != ValueTaskSourceStatus.Pending) { TryInvokeContinuation(); } }
public void ClearStateUponCompletion() { Debug.Assert(IsCompleted); // This logic may be invoked multiple times on the same instance and needs to be robust against that. // If async debugging is enabled, remove the task from tracking. if (s_asyncDebuggingEnabled) { RemoveFromActiveTasks(this); } // Clear out state now that the async method has completed. // This avoids keeping arbitrary state referenced by lifted locals // if this Task / state machine box is held onto. StateMachine = default; Context = default; #if !CORERT // In case this is a state machine box with a finalizer, suppress its finalization // as it's now complete. We only need the finalizer to run if the box is collected // without having been completed. if (AsyncMethodBuilderCore.TrackAsyncMethodCompletion) { GC.SuppressFinalize(this); } #endif }
private void MoveNext(Thread?threadPoolThread) { Debug.Assert(!IsCompleted); bool loggingOn = TplEventSource.Log.IsEnabled(); if (loggingOn) { TplEventSource.Log.TraceSynchronousWorkBegin(this.Id, CausalitySynchronousWork.Execution); } ExecutionContext?context = Context; if (context == null) { Debug.Assert(StateMachine != null); StateMachine.MoveNext(); } else { if (threadPoolThread is null) { ExecutionContext.RunInternal(context, s_callback, this); } else { ExecutionContext.RunFromThreadPoolDispatchLoop(threadPoolThread, context, s_callback, this); } } if (loggingOn) { TplEventSource.Log.TraceSynchronousWorkEnd(CausalitySynchronousWork.Execution); } }
internal void Complete(OperationCompletionFlags completionFlags) { bool cancelled = (completionFlags & OperationCompletionFlags.OperationCancelled) != 0; if (cancelled) { SocketError = SocketError.OperationAborted; } // Reset state. ExecutionContext?context = _context; _context = null; CurrentSocket = null; CurrentOperation = System.Net.Sockets.SocketAsyncOperation.None; // Call OnCompleted only when completed async. bool completedAsync = (completionFlags & OperationCompletionFlags.CompletedSync) == 0; if (completedAsync) { if (context == null) { OnCompleted(this); } else { ExecutionContext.Run(context, s_executionCallback, this); } } }
internal CallbackClosure(ExecutionContext context, AsyncCallback?callback) { if (callback != null) { _savedCallback = callback; _savedContext = context; } }
internal AwaitTaskContinuation(Action action, bool flowExecutionContext) { Action = action; if (flowExecutionContext) { _capturedContext = ExecutionContext.Capture(); } }
private static void OnAddressChanged(IntPtr store, IntPtr changedKeys, IntPtr info) { Dictionary <NetworkAddressChangedEventHandler, ExecutionContext?>? addressChangedSubscribers = null; Dictionary <NetworkAvailabilityChangedEventHandler, ExecutionContext?>?availabilityChangedSubscribers = null; lock (s_lockObj) { if (s_addressChangedSubscribers.Count > 0) { addressChangedSubscribers = new Dictionary <NetworkAddressChangedEventHandler, ExecutionContext?>(s_addressChangedSubscribers); } if (s_availabilityChangedSubscribers.Count > 0) { availabilityChangedSubscribers = new Dictionary <NetworkAvailabilityChangedEventHandler, ExecutionContext?>(s_availabilityChangedSubscribers); } } if (addressChangedSubscribers != null) { foreach (KeyValuePair <NetworkAddressChangedEventHandler, ExecutionContext?> subscriber in addressChangedSubscribers) { NetworkAddressChangedEventHandler handler = subscriber.Key; ExecutionContext?ec = subscriber.Value; if (ec == null) // Flow supressed { handler(null, EventArgs.Empty); } else { ExecutionContext.Run(ec, s_runAddressChangedHandler, handler); } } } if (availabilityChangedSubscribers != null) { bool isAvailable = NetworkInterface.GetIsNetworkAvailable(); NetworkAvailabilityEventArgs args = isAvailable ? s_availableEventArgs : s_notAvailableEventArgs; ContextCallback callbackContext = isAvailable ? s_runHandlerAvailable : s_runHandlerNotAvailable; foreach (KeyValuePair <NetworkAvailabilityChangedEventHandler, ExecutionContext?> subscriber in availabilityChangedSubscribers) { NetworkAvailabilityChangedEventHandler handler = subscriber.Key; ExecutionContext?ec = subscriber.Value; if (ec == null) // Flow supressed { handler(null, args); } else { ExecutionContext.Run(ec, callbackContext, handler); } } } }
/// <summary>Initializes the continuation.</summary> /// <param name="action">The action to invoke. Must not be null.</param> /// <param name="flowExecutionContext">Whether to capture and restore ExecutionContext.</param> internal AwaitTaskContinuation(Action action, bool flowExecutionContext) { Debug.Assert(action != null); m_action = action; if (flowExecutionContext) { m_capturedContext = ExecutionContext.Capture(); } }
// Callback fired when an address change occurs. private static void AddressChangedCallback(object?stateObject, bool signaled) { Dictionary <NetworkAddressChangedEventHandler, ExecutionContext?>?addressChangedSubscribers = null; lock (s_globalLock) { // The listener was canceled, which would only happen if we aren't listening for more events. s_isPending = false; if (!s_isListening) { return; } s_isListening = false; // Need to copy the array so the callback can call start and stop if (s_addressChangedSubscribers.Count > 0) { addressChangedSubscribers = new Dictionary <NetworkAddressChangedEventHandler, ExecutionContext?>(s_addressChangedSubscribers); } try { //wait for the next address change StartHelper(null, false, (StartIPOptions)stateObject !); } catch (NetworkInformationException nie) { if (NetEventSource.Log.IsEnabled()) { NetEventSource.Error(null, nie); } } } // Release the lock before calling into user callback. if (addressChangedSubscribers != null) { foreach (KeyValuePair <NetworkAddressChangedEventHandler, ExecutionContext?> subscriber in addressChangedSubscribers) { NetworkAddressChangedEventHandler handler = subscriber.Key; ExecutionContext?ec = subscriber.Value; if (ec == null) // Flow supressed { handler(null, EventArgs.Empty); } else { ExecutionContext.Run(ec, s_runAddressChangedHandler, handler); } } } }
internal ReadonlyResolveFieldContext Reset(ExecutionNode?node, ExecutionContext?context) { _executionNode = node !; _executionContext = context !; _arguments = null; _subFields = null; _parent = null; return(this); }
internal void StartOperationCommon(Socket socket, System.Net.Sockets.SocketAsyncOperation operation) { CurrentSocket = socket; CurrentOperation = operation; if (_flowExecutionContext) { _context = ExecutionContext.Capture(); } }
public void Reset() { _version++; _completed = false; _result = default(TResult) !; _error = null; _executionContext = null; _capturedContext = null; _continuation = null; _continuationState = null; }
private protected virtual void ResetCore() { Debug.Assert(Monitor.IsEntered(SyncRoot)); version += 1; completed = false; context = null; capturedContext = null; continuation = null; continuationState = null; }
public static void RestoreFlow() { Thread currentThread = Thread.CurrentThread; ExecutionContext?executionContext = currentThread._executionContext; if (executionContext == null || !executionContext.m_isFlowSuppressed) { throw new InvalidOperationException(SR.InvalidOperation_CannotRestoreUnsupressedFlow); } currentThread._executionContext = executionContext.ShallowClone(isFlowSuppressed: false); }
/// <summary>Resets to prepare for the next operation.</summary> public void Reset() { // Reset/update state for the next use/await of this instance. _version++; _completed = false; _result = default; _error = null; _executionContext = null; _capturedContext = null; _continuation = null; _continuationState = null; }
/// <summary>Resets to prepare for the next operation.</summary> public void Reset() { // Reset/update state for the next use/await of this instance. Version++; _result = null; _capturedContext = null; _continuation = null; _continuationState = null; #if TARGETS_NET || TARGETS_NETCORE || GREATERTHAN_NETSTANDARD13 _executionContext = null; #endif }
public PipeAwaitable(bool completed, bool useSynchronizationContext) { _awaitableState = (completed ? AwaitableState.Completed : AwaitableState.None) | (useSynchronizationContext ? AwaitableState.UseSynchronizationContext : AwaitableState.None); _completion = null; _completionState = null; _cancellationTokenRegistration = default; _synchronizationContext = null; _executionContext = null; #if NETSTANDARD2_0 _cancellationToken = CancellationToken.None; #endif }
internal ThreadMethodEntry(Control caller, Control marshaler, Delegate?method, object[]?args, bool synchronous, ExecutionContext?executionContext) { _caller = caller; _marshaler = marshaler; _method = method; _args = args; _exception = null; _retVal = null; _synchronous = synchronous; IsCompleted = false; _resetEvent = null; _executionContext = executionContext; }
/// <summary>Initializes the state object.</summary> protected ForEachAsyncState(Func <object, Task> taskBody, int dop, TaskScheduler scheduler, CancellationToken cancellationToken, Func <TSource, CancellationToken, ValueTask> body) { _taskBody = taskBody; _remainingDop = dop; LoopBody = body; _scheduler = scheduler; if (scheduler == TaskScheduler.Default) { _executionContext = ExecutionContext.Capture(); } _externalCancellationToken = cancellationToken; _registration = cancellationToken.UnsafeRegister(static o => ((ForEachAsyncState <TSource>)o !).Cancellation.Cancel(), this);
// Called from the runtime internal void StartCallback() { ExecutionContext?context = _executionContext; _executionContext = null; if (context != null && !context.IsDefault) { ExecutionContext.RunInternal(context, s_threadStartContextCallback, this); } else { StartCallbackWorker(); } }
// Call this when returning control to the user. internal bool FinishPostingAsyncOp() { // Ignore this call if StartPostingAsyncOp() failed or wasn't called, or this has already been called. if ((_flags & (StateFlags.PostBlockStarted | StateFlags.PostBlockFinished)) != StateFlags.PostBlockStarted) { return(false); } _flags |= StateFlags.PostBlockFinished; ExecutionContext?cachedContext = null; return(CaptureOrComplete(ref cachedContext, false)); }
public static ExecutionContext?Capture() { ExecutionContext?executionContext = Thread.CurrentThread._executionContext; if (executionContext == null) { executionContext = Default; } else if (executionContext.m_isFlowSuppressed) { executionContext = null; } return(executionContext); }