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);
                    }
                }
            }
        }
Esempio n. 2
0
        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();
            }
        }
Esempio n. 6
0
        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);
                }
            }
Esempio n. 8
0
        // 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();
                }
            }
Esempio n. 10
0
            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
            }
Esempio n. 11
0
            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);
                }
            }
Esempio n. 12
0
        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);
                }
            }
        }
Esempio n. 13
0
 internal CallbackClosure(ExecutionContext context, AsyncCallback?callback)
 {
     if (callback != null)
     {
         _savedCallback = callback;
         _savedContext  = context;
     }
 }
Esempio n. 14
0
 internal AwaitTaskContinuation(Action action, bool flowExecutionContext)
 {
     Action = action;
     if (flowExecutionContext)
     {
         _capturedContext = ExecutionContext.Capture();
     }
 }
Esempio n. 15
0
        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);
                    }
                }
            }
        }
Esempio n. 16
0
 /// <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);
                        }
                    }
                }
            }
Esempio n. 18
0
        internal ReadonlyResolveFieldContext Reset(ExecutionNode?node, ExecutionContext?context)
        {
            _executionNode    = node !;
            _executionContext = context !;
            _arguments        = null;
            _subFields        = null;
            _parent           = null;

            return(this);
        }
Esempio n. 19
0
        internal void StartOperationCommon(Socket socket, System.Net.Sockets.SocketAsyncOperation operation)
        {
            CurrentSocket    = socket;
            CurrentOperation = operation;

            if (_flowExecutionContext)
            {
                _context = ExecutionContext.Capture();
            }
        }
Esempio n. 20
0
 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;
        }
Esempio n. 22
0
        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;
 }
Esempio n. 24
0
        /// <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
        }
Esempio n. 26
0
 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;
 }
Esempio n. 27
0
            /// <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);
Esempio n. 28
0
        // 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();
            }
        }
Esempio n. 29
0
        // 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));
        }
Esempio n. 30
0
        public static ExecutionContext?Capture()
        {
            ExecutionContext?executionContext = Thread.CurrentThread._executionContext;

            if (executionContext == null)
            {
                executionContext = Default;
            }
            else if (executionContext.m_isFlowSuppressed)
            {
                executionContext = null;
            }

            return(executionContext);
        }