static BodyDelegate WrapBodyDelegate(ExecutionContext context, BodyDelegate body) { return body == null ? (BodyDelegate)null : (write, flush, end, cancellationToken) => ExecutionContext.Run( context.CreateCopy(), _ => body(write, WrapFlushDelegate(context, flush), end, cancellationToken), null); }
static Func<ArraySegment<byte>, Action<Exception>, TempEnum> WrapWriteDelegate(ExecutionContext context, Func<ArraySegment<byte>, Action<Exception>, TempEnum> write) { return (data, callback) => { if (callback == null) { return write(data, null); } return write(data, ex => ExecutionContext.Run(context.CreateCopy(), state => callback((Exception)state), ex)); }; }
static BodyDelegate WrapBodyDelegate(ExecutionContext context, BodyDelegate body) { if (body == null) { return null; } return (write, end, cancellationToken) => ExecutionContext.Run( context.CreateCopy(), _ => body(WrapWriteDelegate(context, write), end, cancellationToken), null); }
internal static void RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, bool preserveSyncCtx) { Contract.Assert(executionContext != null); if (executionContext.IsPreAllocatedDefault) { Contract.Assert(executionContext.IsDefaultFTContext(preserveSyncCtx)); } else { Contract.Assert(executionContext.isNewCapture); executionContext.isNewCapture = false; } Thread currentThread = Thread.CurrentThread; ExecutionContextSwitcher ecsw = default(ExecutionContextSwitcher); RuntimeHelpers.PrepareConstrainedRegions(); try { ExecutionContext.Reader ec = currentThread.GetExecutionContextReader(); if ((ec.IsNull || ec.IsDefaultFTContext(preserveSyncCtx)) && #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK SecurityContext.CurrentlyInDefaultFTSecurityContext(ec) && #endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK executionContext.IsDefaultFTContext(preserveSyncCtx)) { // Neither context is interesting, so we don't need to set the context. // We do need to reset any changes made by the user's callback, // so here we establish a "copy-on-write scope". Any changes will // result in a copy of the context being made, preserving the original // context. EstablishCopyOnWriteScope(currentThread, true, ref ecsw); } else { if (executionContext.IsPreAllocatedDefault) { executionContext = executionContext.CreateCopy(); } ecsw = SetExecutionContext(executionContext, preserveSyncCtx); } // // Call the user's callback // callback(state); } finally { ecsw.Undo(currentThread); } }
private void FinishPhase(bool observedSense) { // Execute the PHA in try/finally block to reset the variables back in case of it threw an exception if (m_postPhaseAction != null) { try { // Capture the caller thread ID to check if the Add/RemoveParticipant(s) is called from the PHA m_actionCallerID = Thread.CurrentThread.ManagedThreadId; if (m_ownerThreadContext != null) { var currentContext = m_ownerThreadContext; m_ownerThreadContext = m_ownerThreadContext.CreateCopy(); // create a copy for the next run ContextCallback handler = s_invokePostPhaseAction; if (handler == null) { s_invokePostPhaseAction = handler = InvokePostPhaseAction; } ExecutionContext.Run(currentContext, handler, this); #if !PFX_LEGACY_3_5 // Dispose the context directly after using it, // the copy will either be used and siposed in the next phase or in the Dispose currentContext.Dispose(); #endif } else { m_postPhaseAction(this); } m_exception = null; // reset the exception if it was set previously } catch (Exception ex) { m_exception = ex; } finally { m_actionCallerID = 0; SetResetEvents(observedSense); if (m_exception != null) { throw new BarrierPostPhaseException(m_exception); } } } else { SetResetEvents(observedSense); } }
private void FinishPhase(bool observedSense) { // Execute the PHA in try/finally block to reset the variables back in case of it threw an exception if (_postPhaseAction != null) { try { // Capture the caller thread ID to check if the Add/RemoveParticipant(s) is called from the PHA _actionCallerId = Thread.CurrentThread.ManagedThreadId; if (_ownerThreadContext != null) { var currentContext = _ownerThreadContext; _ownerThreadContext = _ownerThreadContext.CreateCopy(); // create a copy for the next run var handler = _invokePostPhaseAction; if (handler == null) { _invokePostPhaseAction = handler = InvokePostPhaseAction; } ExecutionContext.Run(currentContext, handler, this); } else { _postPhaseAction(this); } _exception = null; // reset the exception if it was set previously } catch (Exception ex) { _exception = ex; } finally { _actionCallerId = 0; SetResetEvents(observedSense); if (_exception != null) { throw new BarrierPostPhaseException(_exception); } } } else { SetResetEvents(observedSense); } }
/// <summary> /// Finish the phase by invoking the post phase action, and setting the event, this must be called by the /// last arrival thread /// </summary> /// <param name="observedSense">The current phase sense</param> private void FinishPhase(bool observedSense) { // Execute the PHA in try/finally block to reset the variables back in case of it threw an exception if (m_postPhaseAction != null) { try { // Capture the caller thread ID to check if the Add/RemoveParticipant(s) is called from the PHA m_actionCallerID = Thread.CurrentThread.ManagedThreadId; if (m_ownerThreadContext != null) { ExecutionContext.Run(m_ownerThreadContext.CreateCopy(), i => m_postPhaseAction(this), null); } else { m_postPhaseAction(this); } m_exception = null; // reset the exception if it was set previously } catch (Exception ex) { m_exception = ex; } finally { m_actionCallerID = 0; SetResetEvents(observedSense); if (m_exception != null) { throw new BarrierPostPhaseException(m_exception); } } } else { SetResetEvents(observedSense); } }
private bool CaptureOrComplete(ref ExecutionContext cachedContext, bool returnContext) { bool flag = (base.AsyncCallback != null) || ((this._Flags & StateFlags.CaptureContext) != StateFlags.None); if ((((this._Flags & StateFlags.CaptureIdentity) != StateFlags.None) && !base.InternalPeekCompleted) && (!flag || SecurityContext.IsWindowsIdentityFlowSuppressed())) { this.SafeCaptureIdenity(); } if (flag && !base.InternalPeekCompleted) { if (cachedContext == null) { cachedContext = ExecutionContext.Capture(); } if (cachedContext != null) { if (!returnContext) { this._Context = cachedContext; cachedContext = null; } else { this._Context = cachedContext.CreateCopy(); } } } else { cachedContext = null; } if (base.CompletedSynchronously) { base.Complete(IntPtr.Zero); return true; } return false; }
internal void CallCallback() { if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled(EventLevel.Informational, FrameworkEventSource.Keywords.ThreadTransfer)) { FrameworkEventSource.Log.ThreadTransferReceiveObj(this, 1, string.Empty); } // call directly if EC flow is suppressed if (m_executionContext == null) { m_timerCallback(m_state); } else { using (ExecutionContext executionContext = m_executionContext.IsPreAllocatedDefault ? m_executionContext : m_executionContext.CreateCopy()) { ContextCallback callback = s_callCallbackInContext; if (callback == null) { s_callCallbackInContext = callback = new ContextCallback(CallCallbackInContext); } ExecutionContext.Run( executionContext, callback, this, // state true); // ignoreSyncCtx } } }
internal void CallCallback() { // call directly if EC flow is suppressed if (m_executionContext == null) { m_timerCallback(m_state); } else { using (ExecutionContext executionContext = m_executionContext.IsPreAllocatedDefault ? m_executionContext : m_executionContext.CreateCopy()) { ContextCallback callback = s_callCallbackInContext; if (callback == null) { s_callCallbackInContext = callback = new ContextCallback(CallCallbackInContext); } ExecutionContext.Run( executionContext, callback, this, // state true); // ignoreSyncCtx } } }
internal static void RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, bool preserveSyncCtx) { Contract.Assert(executionContext != null); if (executionContext.IsPreAllocatedDefault) { Contract.Assert(executionContext.IsDefaultFTContext(preserveSyncCtx)); } else { Contract.Assert(executionContext.isNewCapture); executionContext.isNewCapture = false; } Thread currentThread = Thread.CurrentThread; ExecutionContextSwitcher ecsw = default(ExecutionContextSwitcher); RuntimeHelpers.PrepareConstrainedRegions(); try { ExecutionContext.Reader ec = currentThread.GetExecutionContextReader(); if ( (ec.IsNull || ec.IsDefaultFTContext(preserveSyncCtx)) && #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK SecurityContext.CurrentlyInDefaultFTSecurityContext(ec) && #endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK executionContext.IsDefaultFTContext(preserveSyncCtx)) { // Neither context is interesting, so we don't need to set the context. // We do need to reset any changes made by the user's callback, // so here we establish a "copy-on-write scope". Any changes will // result in a copy of the context being made, preserving the original // context. EstablishCopyOnWriteScope(currentThread, true, ref ecsw); } else { if (executionContext.IsPreAllocatedDefault) executionContext = executionContext.CreateCopy(); ecsw = SetExecutionContext(executionContext, preserveSyncCtx); } // // Call the user's callback // callback(state); } finally { ecsw.Undo(currentThread); } }
// This must be called right before returning the result to the user. It might call the callback itself, // to avoid flowing context. Even if the operation completes before this call, the callback won't have been // called. // // Returns whether the operation completed sync or not. private bool CaptureOrComplete(ref ExecutionContext cachedContext, bool returnContext) { GlobalLog.Assert((_flags & StateFlags.PostBlockStarted) != 0, "ContextAwareResult#{0}::CaptureOrComplete|Called without calling StartPostingAsyncOp.", Logging.HashString(this)); // See if we're going to need to capture the context. bool capturingContext = AsyncCallback != null || (_flags & StateFlags.CaptureContext) != 0; // Peek if we've already completed, but don't fix CompletedSynchronously yet // Capture the identity if requested, unless we're going to capture the context anyway, unless // capturing the context won't be sufficient. if ((_flags & StateFlags.CaptureIdentity) != 0 && !InternalPeekCompleted && (!capturingContext)) { GlobalLog.Print("ContextAwareResult#" + Logging.HashString(this) + "::CaptureOrComplete() starting identity capture"); SafeCaptureIdentity(); } // No need to flow if there's no callback, unless it's been specifically requested. // Note that Capture() can return null, for example if SuppressFlow() is in effect. if (capturingContext && !InternalPeekCompleted) { GlobalLog.Print("ContextAwareResult#" + Logging.HashString(this) + "::CaptureOrComplete() starting capture"); if (cachedContext == null) { cachedContext = ExecutionContext.Capture(); } if (cachedContext != null) { if (!returnContext) { _context = cachedContext; cachedContext = null; } else { _context = cachedContext.CreateCopy(); } } GlobalLog.Print("ContextAwareResult#" + Logging.HashString(this) + "::CaptureOrComplete() _Context:" + Logging.HashString(_context)); } else { // Otherwise we have to have completed synchronously, or not needed the context. GlobalLog.Print("ContextAwareResult#" + Logging.HashString(this) + "::CaptureOrComplete() skipping capture"); cachedContext = null; GlobalLog.Assert(AsyncCallback == null || CompletedSynchronously, "ContextAwareResult#{0}::CaptureOrComplete|Didn't capture context, but didn't complete synchronously!", Logging.HashString(this)); } // Now we want to see for sure what to do. We might have just captured the context for no reason. // This has to be the first time the state has been queried "for real" (apart from InvokeCallback) // to guarantee synchronization with Complete() (otherwise, Complete() could try to call the // callback without the context having been gotten). DebugProtectState(false); if (CompletedSynchronously) { GlobalLog.Print("ContextAwareResult#" + Logging.HashString(this) + "::CaptureOrComplete() completing synchronously"); base.Complete(IntPtr.Zero); return true; } return false; }
static Func<Action, bool> WrapFlushDelegate(ExecutionContext context, Func<Action, bool> flush) { return drained => drained == null ? flush(null) : flush(() => ExecutionContext.Run(context.CreateCopy(), _ => drained(), null)); }
static Func<ArraySegment<byte>, Action, bool> WrapWriteDelegate(ExecutionContext context, Func<ArraySegment<byte>, Action, bool> write) { return (data, callback) => callback == null ? write(data, null) : write(data, () => ExecutionContext.Run(context.CreateCopy(), _ => callback(), null)); }