#if MONO using System; using System.Diagnostics; using System.Runtime; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security; using System.Security.Permissions; namespace System.Threading { [Serializable] internal enum StackCrawlMark { LookForMe, LookForMyCaller, LookForMyCallersCaller, LookForThread } /// Propagates notification that operations should be canceled. [__DynamicallyInvokable, DebuggerDisplay("IsCancellationRequested = {IsCancellationRequested}"), ComVisible(false)] [HostProtection(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)] public struct CancellationToken { private CancellationTokenSource m_source; private static readonly Action s_ActionToActionObjShunt = new Action(CancellationToken.ActionToActionObjShunt); /// Returns an empty CancellationToken value. /// Returns an empty CancellationToken value. [__DynamicallyInvokable] public static CancellationToken None { [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] get { return default(CancellationToken); } } /// Gets whether cancellation has been requested for this token. /// true if cancellation has been requested for this token; otherwise false. [__DynamicallyInvokable] public bool IsCancellationRequested { [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] get { return this.m_source != null && this.m_source.IsCancellationRequested; } } /// Gets whether this token is capable of being in the canceled state. /// true if this token is capable of being in the canceled state; otherwise false. [__DynamicallyInvokable] public bool CanBeCanceled { [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] get { return this.m_source != null && this.m_source.CanBeCanceled; } } /// Gets a that is signaled when the token is canceled. /// A that is signaled when the token is canceled. /// The associated has been disposed. [__DynamicallyInvokable] public WaitHandle WaitHandle { [__DynamicallyInvokable] get { if (this.m_source == null) { this.InitializeDefaultSource(); } return this.m_source.WaitHandle; } } [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] internal CancellationToken(CancellationTokenSource source) { this.m_source = source; } /// Initializes the . /// The canceled state for the token. [__DynamicallyInvokable] public CancellationToken(bool canceled) { this = default(CancellationToken); if (canceled) { this.m_source = CancellationTokenSource.InternalGetStaticSource(canceled); } } /// Registers a delegate that will be called when this is canceled. /// The instance that can be used to deregister the callback. /// The delegate to be executed when the is canceled. /// The associated has been disposed. /// /// is null. [__DynamicallyInvokable] public CancellationTokenRegistration Register(Action callback) { if (callback == null) { throw new ArgumentNullException("callback"); } return this.Register(CancellationToken.s_ActionToActionObjShunt, callback, false, true); } /// Registers a delegate that will be called when this is canceled. /// The instance that can be used to deregister the callback. /// The delegate to be executed when the is canceled. /// A Boolean value that indicates whether to capture the current and use it when invoking the . /// The associated has been disposed. /// /// is null. [__DynamicallyInvokable] public CancellationTokenRegistration Register(Action callback, bool useSynchronizationContext) { if (callback == null) { throw new ArgumentNullException("callback"); } return this.Register(CancellationToken.s_ActionToActionObjShunt, callback, useSynchronizationContext, true); } /// Registers a delegate that will be called when this is canceled. /// The instance that can be used to deregister the callback. /// The delegate to be executed when the is canceled. /// The state to pass to the when the delegate is invoked. This may be null. /// The associated has been disposed. /// /// is null. [__DynamicallyInvokable] public CancellationTokenRegistration Register(Action callback, object state) { if (callback == null) { throw new ArgumentNullException("callback"); } return this.Register(callback, state, false, true); } /// Registers a delegate that will be called when this is canceled. /// The instance that can be used to deregister the callback. /// The delegate to be executed when the is canceled. /// The state to pass to the when the delegate is invoked. This may be null. /// A Boolean value that indicates whether to capture the current and use it when invoking the . /// The associated has been disposed. /// /// is null. [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] public CancellationTokenRegistration Register(Action callback, object state, bool useSynchronizationContext) { return this.Register(callback, state, useSynchronizationContext, true); } [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] internal CancellationTokenRegistration InternalRegisterWithoutEC(Action callback, object state) { return this.Register(callback, state, false, false); } [SecuritySafeCritical] [MethodImpl(MethodImplOptions.NoInlining)] private CancellationTokenRegistration Register(Action callback, object state, bool useSynchronizationContext, bool useExecutionContext) { StackCrawlMark stackCrawlMark = StackCrawlMark.LookForMyCaller; if (callback == null) { throw new ArgumentNullException("callback"); } if (!this.CanBeCanceled) { return default(CancellationTokenRegistration); } SynchronizationContext targetSyncContext = null; ExecutionContext executionContext = null; if (!this.IsCancellationRequested) { if (useSynchronizationContext) { targetSyncContext = SynchronizationContext.Current; } if (useExecutionContext) { //executionContext = ExecutionContext.Capture(ref stackCrawlMark, ExecutionContext.CaptureOptions.OptimizeDefaultCase); executionContext = ExecutionContext.Capture(); } } return this.m_source.InternalRegister(callback, state, targetSyncContext, executionContext); } /// Determines whether the current instance is equal to the specified token. /// True if the instances are equal; otherwise, false. Two tokens are equal if they are associated with the same or if they were both constructed from public CancellationToken constructors and their values are equal. /// The other to which to compare this instance. [__DynamicallyInvokable] public bool Equals(CancellationToken other) { if (this.m_source == null && other.m_source == null) { return true; } if (this.m_source == null) { return other.m_source == CancellationTokenSource.InternalGetStaticSource(false); } if (other.m_source == null) { return this.m_source == CancellationTokenSource.InternalGetStaticSource(false); } return this.m_source == other.m_source; } /// Determines whether the current instance is equal to the specified . /// True if is a and if the two instances are equal; otherwise, false. Two tokens are equal if they are associated with the same or if they were both constructed from public CancellationToken constructors and their values are equal. /// The other object to which to compare this instance. /// An associated has been disposed. [__DynamicallyInvokable] public override bool Equals(object other) { return other is CancellationToken && this.Equals((CancellationToken)other); } /// Serves as a hash function for a . /// A hash code for the current instance. [__DynamicallyInvokable] public override int GetHashCode() { if (this.m_source == null) { return CancellationTokenSource.InternalGetStaticSource(false).GetHashCode(); } return this.m_source.GetHashCode(); } /// Determines whether two instances are equal. /// True if the instances are equal; otherwise, false. /// The first instance. /// The second instance. /// An associated has been disposed. [__DynamicallyInvokable] public static bool operator ==(CancellationToken left, CancellationToken right) { return left.Equals(right); } /// Determines whether two instances are not equal. /// True if the instances are not equal; otherwise, false. /// The first instance. /// The second instance. /// An associated has been disposed. [__DynamicallyInvokable] public static bool operator !=(CancellationToken left, CancellationToken right) { return !left.Equals(right); } /// Throws a if this token has had cancellation requested. /// The token has had cancellation requested. /// The associated has been disposed. [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] public void ThrowIfCancellationRequested() { if (this.IsCancellationRequested) { this.ThrowOperationCanceledException(); } } internal void ThrowIfSourceDisposed() { if (this.m_source != null && this.m_source.IsDisposed) { CancellationToken.ThrowObjectDisposedException(); } } private void ThrowOperationCanceledException() { throw new OperationCanceledException("OperationCanceled"); } private static void ActionToActionObjShunt(object obj) { Action action = obj as Action; action(); } private static void ThrowObjectDisposedException() { throw new ObjectDisposedException(null, "CancellationToken_SourceDisposed"); } private void InitializeDefaultSource() { this.m_source = CancellationTokenSource.InternalGetStaticSource(false); } } } #endif