コード例 #1
0
        // the worker method to actually run the callback
        // The signature is such that it can be used as a 'ContextCallback'
        private static void ExecutionContextCallback(object obj)
        {
            CancellationCallbackInfo callbackInfo = obj as CancellationCallbackInfo;

            Contract.Assert(callbackInfo != null);
            callbackInfo.Callback(callbackInfo.StateForCallback);
        }
コード例 #2
0
        /// <summary>
        /// Registers a callback object. If cancellation has already occurred, the
        /// callback will have been run by the time this method returns.
        /// </summary>
        internal CancellationTokenRegistration InternalRegister(
            Action <object> callback, object stateForCallback, SynchronizationContext targetSyncContext, ExecutionContext executionContext)
        {
            ThrowIfDisposed();

            // the CancellationToken has already checked that the token is cancelable before calling this method.
            Contract.Assert(CanBeCanceled, "Cannot register for uncancelable token src");

            // if not canceled, register the event handlers
            // if canceled already, run the callback synchronously
            // Apart from the semantics of late-enlistment, this also ensures that during ExecuteCallbackHandlers() there
            // will be no mutation of the _registeredCallbacks list

            if (!IsCancellationRequested)
            {
                int myIndex = Thread.CurrentThread.ManagedThreadId % s_nLists;

                CancellationCallbackInfo callbackInfo = new CancellationCallbackInfo(callback, stateForCallback, targetSyncContext, executionContext, this);

                //allocate the callback list array
                if (m_registeredCallbacksLists == null)
                {
                    SparselyPopulatedArray <CancellationCallbackInfo>[] list = new SparselyPopulatedArray <CancellationCallbackInfo> [s_nLists];
                    Interlocked.CompareExchange(ref m_registeredCallbacksLists, list, null);
                }

                //allocate the actual lists on-demand to save mem in low-use situations, and to avoid false-sharing.
                if (m_registeredCallbacksLists[myIndex] == null)
                {
                    SparselyPopulatedArray <CancellationCallbackInfo> callBackArray = new SparselyPopulatedArray <CancellationCallbackInfo>(4);
                    Interlocked.CompareExchange(ref (m_registeredCallbacksLists[myIndex]), callBackArray, null);
                }

                // Now add the registration to the list.
                SparselyPopulatedArray <CancellationCallbackInfo>        callbacks = m_registeredCallbacksLists[myIndex];
                SparselyPopulatedArrayAddInfo <CancellationCallbackInfo> addInfo   = callbacks.Add(callbackInfo);
                CancellationTokenRegistration registration = new CancellationTokenRegistration(this, callbackInfo, addInfo);

                if (!IsCancellationRequested)
                {
                    return(registration);
                }

                //If a cancellation has since come in, we will try to undo the registration and run the callback directly here.
                bool deregisterOccurred = registration.TryDeregister();

                if (!deregisterOccurred)
                {
                    // the callback execution process must have snagged the callback for execution, so
                    // 1. wait for the callback to complete, then
                    // 2. return a dummy registration.
                    WaitForCallbackToComplete(callbackInfo);
                    return(new CancellationTokenRegistration());
                }
            }

            // If cancellation already occurred, we run the callback on this thread and return an empty registration.
            callback(stateForCallback);
            return(new CancellationTokenRegistration());
        }
コード例 #3
0
 internal CancellationTokenRegistration InternalRegister(Action <object> callback, object stateForCallback, SynchronizationContext targetSyncContext, ExecutionContext executionContext)
 {
     this.ThrowIfDisposed();
     if (!this.IsCancellationRequested)
     {
         int index = Thread.CurrentThread.ManagedThreadId % s_nLists;
         CancellationCallbackInfo element = new CancellationCallbackInfo(callback, stateForCallback, targetSyncContext, executionContext, this);
         if (this.m_registeredCallbacksLists == null)
         {
             SparselyPopulatedArray <CancellationCallbackInfo>[] arrayArray = new SparselyPopulatedArray <CancellationCallbackInfo> [s_nLists];
             Interlocked.CompareExchange <SparselyPopulatedArray <CancellationCallbackInfo>[]>(ref this.m_registeredCallbacksLists, arrayArray, null);
         }
         if (this.m_registeredCallbacksLists[index] == null)
         {
             SparselyPopulatedArray <CancellationCallbackInfo> array = new SparselyPopulatedArray <CancellationCallbackInfo>(4);
             Interlocked.CompareExchange <SparselyPopulatedArray <CancellationCallbackInfo> >(ref this.m_registeredCallbacksLists[index], array, null);
         }
         SparselyPopulatedArrayAddInfo <CancellationCallbackInfo> registrationInfo = this.m_registeredCallbacksLists[index].Add(element);
         CancellationTokenRegistration registration = new CancellationTokenRegistration(this, element, registrationInfo);
         if (!this.IsCancellationRequested)
         {
             return(registration);
         }
         if (!registration.TryDeregister())
         {
             this.WaitForCallbackToComplete(element);
             return(new CancellationTokenRegistration());
         }
     }
     callback(stateForCallback);
     return(new CancellationTokenRegistration());
 }
コード例 #4
0
 internal CancellationTokenRegistration(
     CancellationCallbackInfo callbackInfo,
     SparselyPopulatedArrayAddInfo <CancellationCallbackInfo> registrationInfo)
 {
     m_callbackInfo     = callbackInfo;
     m_registrationInfo = registrationInfo;
 }
コード例 #5
0
        // Wait for a single callback to complete (or, more specifically, to not be running).
        // It is ok to call this method if the callback has already finished.
        // Calling this method before the target callback has been selected for execution would be an error.
        internal void WaitForCallbackToComplete(CancellationCallbackInfo callbackInfo)
        {
            SpinWait sw = new SpinWait();

            while (ExecutingCallback == callbackInfo)
            {
                sw.SpinOnce();  //spin as we assume callback execution is fast and that this situation is rare.
            }
        }
コード例 #6
0
        internal void WaitForCallbackToComplete(CancellationCallbackInfo callbackInfo)
        {
            SpinWait spinWait = new SpinWait();

            while (this.ExecutingCallback == callbackInfo)
            {
                spinWait.SpinOnce();
            }
        }
コード例 #7
0
        internal bool TryDeregister()
        {
            if (this.m_registrationInfo.Source == null)
            {
                return(false);
            }
            CancellationCallbackInfo cancellationCallbackInfo = this.m_registrationInfo.Source.SafeAtomicRemove(this.m_registrationInfo.Index, this.m_callbackInfo);

            return(cancellationCallbackInfo == this.m_callbackInfo);
        }
コード例 #8
0
        private void CancellationCallbackCoreWork(CancellationCallbackCoreWorkArguments args)
        {
            CancellationCallbackInfo cancellationCallbackInfo = args.m_currArrayFragment.SafeAtomicRemove(args.m_currArrayIndex, this.m_executingCallback);

            if (cancellationCallbackInfo == this.m_executingCallback)
            {
                if (cancellationCallbackInfo.TargetExecutionContext != null)
                {
                    cancellationCallbackInfo.CancellationTokenSource.ThreadIDExecutingCallbacks = Thread.CurrentThread.ManagedThreadId;
                }
                cancellationCallbackInfo.ExecuteCallback();
            }
        }
コード例 #9
0
 internal void ExecuteCallback()
 {
     if (this.TargetExecutionContext != null)
     {
         ContextCallback contextCallback = CancellationCallbackInfo.s_executionContextCallback;
         if (contextCallback == null)
         {
             contextCallback = (CancellationCallbackInfo.s_executionContextCallback = new ContextCallback(CancellationCallbackInfo.ExecutionContextCallback));
         }
         ExecutionContext.Run(this.TargetExecutionContext, contextCallback, this);
         return;
     }
     CancellationCallbackInfo.ExecutionContextCallback(this);
 }
コード例 #10
0
        private void CancellationCallbackCoreWork_OnSyncContext(object obj)
        {
            CancellationCallbackCoreWorkArguments arguments = (CancellationCallbackCoreWorkArguments)obj;
            CancellationCallbackInfo info = arguments.m_currArrayFragment.SafeAtomicRemove(arguments.m_currArrayIndex, this.m_executingCallback);

            if (info == this.m_executingCallback)
            {
                if (info.TargetExecutionContext != null)
                {
                    info.CancellationTokenSource.ThreadIDExecutingCallbacks = Thread.CurrentThread.ManagedThreadId;
                }
                info.ExecuteCallback();
            }
        }
コード例 #11
0
        public void Dispose()
        {
            bool flag = this.TryDeregister();
            CancellationCallbackInfo callbackInfo = this.m_callbackInfo;

            if (callbackInfo != null)
            {
                CancellationTokenSource cancellationTokenSource = callbackInfo.CancellationTokenSource;
                if (cancellationTokenSource.IsCancellationRequested && !cancellationTokenSource.IsCancellationCompleted && !flag && cancellationTokenSource.ThreadIDExecutingCallbacks != Thread.CurrentThread.ManagedThreadId)
                {
                    cancellationTokenSource.WaitForCallbackToComplete(this.m_callbackInfo);
                }
            }
        }
コード例 #12
0
 internal void ExecuteCallback()
 {
     if (this.TargetExecutionContext != null)
     {
         ContextCallback callback = CancellationCallbackInfo.s_executionContextCallback;
         if (callback == null)
         {
             CancellationCallbackInfo.s_executionContextCallback = callback = new ContextCallback(CancellationCallbackInfo.ExecutionContextCallback);
         }
         ExecutionContext.Run(this.TargetExecutionContext, callback, (object)this);
     }
     else
     {
         CancellationCallbackInfo.ExecutionContextCallback((object)this);
     }
 }
コード例 #13
0
        public void Dispose()
        {
            bool flag = this.TryDeregister();
            CancellationCallbackInfo cancellationCallbackInfo = this.m_callbackInfo;

            if (cancellationCallbackInfo == null)
            {
                return;
            }
            CancellationTokenSource cancellationTokenSource = cancellationCallbackInfo.CancellationTokenSource;

            if (!cancellationTokenSource.IsCancellationRequested || cancellationTokenSource.IsCancellationCompleted || (flag || cancellationTokenSource.ThreadIDExecutingCallbacks == Thread.CurrentThread.ManagedThreadId))
            {
                return;
            }
            cancellationTokenSource.WaitForCallbackToComplete(this.m_callbackInfo);
        }
コード例 #14
0
 // Token: 0x06003E40 RID: 15936 RVA: 0x000E71FC File Offset: 0x000E53FC
 internal CancellationTokenRegistration InternalRegister(Action <object> callback, object stateForCallback, SynchronizationContext targetSyncContext, ExecutionContext executionContext)
 {
     if (AppContextSwitches.ThrowExceptionIfDisposedCancellationTokenSource)
     {
         this.ThrowIfDisposed();
     }
     if (!this.IsCancellationRequested)
     {
         if (this.m_disposed && !AppContextSwitches.ThrowExceptionIfDisposedCancellationTokenSource)
         {
             return(default(CancellationTokenRegistration));
         }
         int num = Thread.CurrentThread.ManagedThreadId % CancellationTokenSource.s_nLists;
         CancellationCallbackInfo cancellationCallbackInfo         = new CancellationCallbackInfo(callback, stateForCallback, targetSyncContext, executionContext, this);
         SparselyPopulatedArray <CancellationCallbackInfo>[] array = this.m_registeredCallbacksLists;
         if (array == null)
         {
             SparselyPopulatedArray <CancellationCallbackInfo>[] array2 = new SparselyPopulatedArray <CancellationCallbackInfo> [CancellationTokenSource.s_nLists];
             array = Interlocked.CompareExchange <SparselyPopulatedArray <CancellationCallbackInfo>[]>(ref this.m_registeredCallbacksLists, array2, null);
             if (array == null)
             {
                 array = array2;
             }
         }
         SparselyPopulatedArray <CancellationCallbackInfo> sparselyPopulatedArray = Volatile.Read <SparselyPopulatedArray <CancellationCallbackInfo> >(ref array[num]);
         if (sparselyPopulatedArray == null)
         {
             SparselyPopulatedArray <CancellationCallbackInfo> value = new SparselyPopulatedArray <CancellationCallbackInfo>(4);
             Interlocked.CompareExchange <SparselyPopulatedArray <CancellationCallbackInfo> >(ref array[num], value, null);
             sparselyPopulatedArray = array[num];
         }
         SparselyPopulatedArrayAddInfo <CancellationCallbackInfo> registrationInfo = sparselyPopulatedArray.Add(cancellationCallbackInfo);
         CancellationTokenRegistration result = new CancellationTokenRegistration(cancellationCallbackInfo, registrationInfo);
         if (!this.IsCancellationRequested)
         {
             return(result);
         }
         if (!result.TryDeregister())
         {
             return(result);
         }
     }
     callback(stateForCallback);
     return(default(CancellationTokenRegistration));
 }
コード例 #15
0
        internal bool TryDeregister()
        {
            if (m_registrationInfo.Source == null)  //can be null for dummy registrations.
            {
                return(false);
            }

            // Try to remove the callback info from the array.
            // It is possible the callback info is missing (removed for run, or removed by someone else)
            // It is also possible there is info in the array but it doesn't match our current registration's callback info.
            CancellationCallbackInfo prevailingCallbackInfoInSlot = m_registrationInfo.Source.SafeAtomicRemove(m_registrationInfo.Index, m_callbackInfo);

            if (prevailingCallbackInfoInSlot != m_callbackInfo)
            {
                return(false);  //the callback in the slot wasn't us.
            }
            return(true);
        }
コード例 #16
0
        // The main callback work that executes on the target synchronization context
        private void CancellationCallbackCoreWork_OnSyncContext(object obj)
        {
            CancellationCallbackCoreWorkArguments args = (CancellationCallbackCoreWorkArguments)obj;

            // now remove the intended callback..and ensure that it worked.
            // otherwise the callback has disappeared in the interim and we can immediately return.
            CancellationCallbackInfo callback = args.m_currArrayFragment.SafeAtomicRemove(args.m_currArrayIndex, m_executingCallback);

            if (callback == m_executingCallback)
            {
                if (callback.TargetExecutionContext != null)
                {
                    // we are running via a custom sync context, so update the executing threadID
                    callback.CancellationTokenSource.ThreadIDExecutingCallbacks = Thread.CurrentThread.ManagedThreadId;
                }
                callback.ExecuteCallback();
            }
        }
コード例 #17
0
 internal CancellationTokenRegistration InternalRegister(Action <object> callback, object stateForCallback, SynchronizationContext targetSyncContext, ExecutionContext executionContext)
 {
     if (AppContextSwitches.ThrowExceptionIfDisposedCancellationTokenSource)
     {
         this.ThrowIfDisposed();
     }
     if (!this.IsCancellationRequested)
     {
         if (this.m_disposed && !AppContextSwitches.ThrowExceptionIfDisposedCancellationTokenSource)
         {
             return(new CancellationTokenRegistration());
         }
         int index = Thread.CurrentThread.ManagedThreadId % CancellationTokenSource.s_nLists;
         CancellationCallbackInfo cancellationCallbackInfo = new CancellationCallbackInfo(callback, stateForCallback, targetSyncContext, executionContext, this);
         SparselyPopulatedArray <CancellationCallbackInfo>[] sparselyPopulatedArrayArray1 = this.m_registeredCallbacksLists;
         if (sparselyPopulatedArrayArray1 == null)
         {
             SparselyPopulatedArray <CancellationCallbackInfo>[] sparselyPopulatedArrayArray2 = new SparselyPopulatedArray <CancellationCallbackInfo> [CancellationTokenSource.s_nLists];
             sparselyPopulatedArrayArray1 = Interlocked.CompareExchange <SparselyPopulatedArray <CancellationCallbackInfo>[]>(ref this.m_registeredCallbacksLists, sparselyPopulatedArrayArray2, (SparselyPopulatedArray <CancellationCallbackInfo>[])null) ?? sparselyPopulatedArrayArray2;
         }
         SparselyPopulatedArray <CancellationCallbackInfo> sparselyPopulatedArray1 = Volatile.Read <SparselyPopulatedArray <CancellationCallbackInfo> >(ref sparselyPopulatedArrayArray1[index]);
         if (sparselyPopulatedArray1 == null)
         {
             SparselyPopulatedArray <CancellationCallbackInfo> sparselyPopulatedArray2 = new SparselyPopulatedArray <CancellationCallbackInfo>(4);
             Interlocked.CompareExchange <SparselyPopulatedArray <CancellationCallbackInfo> >(ref sparselyPopulatedArrayArray1[index], sparselyPopulatedArray2, (SparselyPopulatedArray <CancellationCallbackInfo>)null);
             sparselyPopulatedArray1 = sparselyPopulatedArrayArray1[index];
         }
         SparselyPopulatedArrayAddInfo <CancellationCallbackInfo> registrationInfo = sparselyPopulatedArray1.Add(cancellationCallbackInfo);
         CancellationTokenRegistration tokenRegistration = new CancellationTokenRegistration(cancellationCallbackInfo, registrationInfo);
         if (!this.IsCancellationRequested || !tokenRegistration.TryDeregister())
         {
             return(tokenRegistration);
         }
     }
     callback(stateForCallback);
     return(new CancellationTokenRegistration());
 }
コード例 #18
0
        private static void ExecutionContextCallback(object obj)
        {
            CancellationCallbackInfo cancellationCallbackInfo = obj as CancellationCallbackInfo;

            cancellationCallbackInfo.Callback(cancellationCallbackInfo.StateForCallback);
        }
コード例 #19
0
        private void ExecuteCallbackHandlers(bool throwOnFirstException)
        {
            List <Exception> exceptionList = (List <Exception>)null;

            SparselyPopulatedArray <CancellationCallbackInfo>[] sparselyPopulatedArrayArray = this.m_registeredCallbacksLists;
            if (sparselyPopulatedArrayArray == null)
            {
                Interlocked.Exchange(ref this.m_state, 3);
            }
            else
            {
                try
                {
                    for (int index = 0; index < sparselyPopulatedArrayArray.Length; ++index)
                    {
                        SparselyPopulatedArray <CancellationCallbackInfo> sparselyPopulatedArray = Volatile.Read <SparselyPopulatedArray <CancellationCallbackInfo> >(ref sparselyPopulatedArrayArray[index]);
                        if (sparselyPopulatedArray != null)
                        {
                            for (SparselyPopulatedArrayFragment <CancellationCallbackInfo> currArrayFragment = sparselyPopulatedArray.Tail; currArrayFragment != null; currArrayFragment = currArrayFragment.Prev)
                            {
                                for (int currArrayIndex = currArrayFragment.Length - 1; currArrayIndex >= 0; --currArrayIndex)
                                {
                                    this.m_executingCallback = currArrayFragment[currArrayIndex];
                                    if (this.m_executingCallback != null)
                                    {
                                        CancellationCallbackCoreWorkArguments args = new CancellationCallbackCoreWorkArguments(currArrayFragment, currArrayIndex);
                                        try
                                        {
                                            if (this.m_executingCallback.TargetSyncContext != null)
                                            {
                                                this.m_executingCallback.TargetSyncContext.Send(new SendOrPostCallback(this.CancellationCallbackCoreWork_OnSyncContext), (object)args);
                                                this.ThreadIDExecutingCallbacks = Thread.CurrentThread.ManagedThreadId;
                                            }
                                            else
                                            {
                                                this.CancellationCallbackCoreWork(args);
                                            }
                                        }
                                        catch (Exception ex)
                                        {
                                            if (throwOnFirstException)
                                            {
                                                throw;
                                            }
                                            else
                                            {
                                                if (exceptionList == null)
                                                {
                                                    exceptionList = new List <Exception>();
                                                }
                                                exceptionList.Add(ex);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                finally
                {
                    this.m_state             = 3;
                    this.m_executingCallback = (CancellationCallbackInfo)null;
                    Thread.MemoryBarrier();
                }
                if (exceptionList != null)
                {
                    throw new AggregateException((IEnumerable <Exception>)exceptionList);
                }
            }
        }
コード例 #20
0
 internal CancellationTokenRegistration InternalRegister(Action<object> callback, object stateForCallback, SynchronizationContext targetSyncContext, ExecutionContext executionContext)
 {
     ThrowIfDisposed();
     if (!IsCancellationRequested)
     {
         var index = Thread.CurrentThread.ManagedThreadId % _nLists;
         var element = new CancellationCallbackInfo(callback, stateForCallback, targetSyncContext, executionContext, this);
         var registeredCallbacksLists = _registeredCallbacksLists;
         if (registeredCallbacksLists == null)
         {
             var arrayArray2 = new SparselyPopulatedArray<CancellationCallbackInfo>[_nLists];
             registeredCallbacksLists = Interlocked.CompareExchange<SparselyPopulatedArray<CancellationCallbackInfo>[]>(ref _registeredCallbacksLists, arrayArray2, null);
             if (registeredCallbacksLists == null)
                 registeredCallbacksLists = arrayArray2;
         }
         var array = Volatile.Read<SparselyPopulatedArray<CancellationCallbackInfo>>(ref registeredCallbacksLists[index]);
         if (array == null)
         {
             var array2 = new SparselyPopulatedArray<CancellationCallbackInfo>(4);
             Interlocked.CompareExchange<SparselyPopulatedArray<CancellationCallbackInfo>>(ref registeredCallbacksLists[index], array2, null);
             array = registeredCallbacksLists[index];
         }
         var registrationInfo = array.Add(element);
         var registration = new CancellationTokenRegistration(element, registrationInfo);
         if (!IsCancellationRequested)
             return registration;
         if (!registration.TryDeregister())
             return registration;
     }
     callback(stateForCallback);
     return new CancellationTokenRegistration();
 }
コード例 #21
0
        private void ExecuteCallbackHandlers(bool throwOnFirstException)
        {
            List <Exception> innerExceptions = null;

            SparselyPopulatedArray <CancellationCallbackInfo>[] registeredCallbacksLists = this.m_registeredCallbacksLists;
            if (registeredCallbacksLists == null)
            {
                Interlocked.Exchange(ref this.m_state, 3);
            }
            else
            {
                try
                {
                    for (int i = 0; i < registeredCallbacksLists.Length; i++)
                    {
                        SparselyPopulatedArray <CancellationCallbackInfo> array = registeredCallbacksLists[i];
                        if (array != null)
                        {
                            for (SparselyPopulatedArrayFragment <CancellationCallbackInfo> fragment = array.Tail; fragment != null; fragment = fragment.Prev)
                            {
                                for (int j = fragment.Length - 1; j >= 0; j--)
                                {
                                    this.m_executingCallback = fragment[j];
                                    if (this.m_executingCallback != null)
                                    {
                                        CancellationCallbackCoreWorkArguments state = new CancellationCallbackCoreWorkArguments(fragment, j);
                                        try
                                        {
                                            if (this.m_executingCallback.TargetSyncContext != null)
                                            {
                                                this.m_executingCallback.TargetSyncContext.Send(new SendOrPostCallback(this.CancellationCallbackCoreWork_OnSyncContext), state);
                                                this.ThreadIDExecutingCallbacks = Thread.CurrentThread.ManagedThreadId;
                                            }
                                            else
                                            {
                                                this.CancellationCallbackCoreWork_OnSyncContext(state);
                                            }
                                        }
                                        catch (Exception exception)
                                        {
                                            if (throwOnFirstException)
                                            {
                                                throw;
                                            }
                                            if (innerExceptions == null)
                                            {
                                                innerExceptions = new List <Exception>();
                                            }
                                            innerExceptions.Add(exception);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                finally
                {
                    this.m_state             = 3;
                    this.m_executingCallback = null;
                    Thread.MemoryBarrier();
                }
                if (innerExceptions != null)
                {
                    throw new AggregateException(innerExceptions);
                }
            }
        }
コード例 #22
0
ファイル: CancellationTokenSource.cs プロジェクト: rmc00/gsf
 internal CancellationTokenRegistration InternalRegister(Action<object> callback, object stateForCallback, SynchronizationContext targetSyncContext, ExecutionContext executionContext)
 {
     this.ThrowIfDisposed();
     if (!this.IsCancellationRequested)
     {
         int num = Thread.CurrentThread.ManagedThreadId % CancellationTokenSource.s_nLists;
         CancellationCallbackInfo cancellationCallbackInfo = new CancellationCallbackInfo(callback, stateForCallback, targetSyncContext, executionContext, this);
         SparselyPopulatedArray<CancellationCallbackInfo>[] array = this.m_registeredCallbacksLists;
         if (array == null)
         {
             SparselyPopulatedArray<CancellationCallbackInfo>[] array2 = new SparselyPopulatedArray<CancellationCallbackInfo>[CancellationTokenSource.s_nLists];
             array = Interlocked.CompareExchange<SparselyPopulatedArray<CancellationCallbackInfo>[]>(ref this.m_registeredCallbacksLists, array2, null);
             if (array == null)
             {
                 array = array2;
             }
         }
         SparselyPopulatedArray<CancellationCallbackInfo> sparselyPopulatedArray = Volatile.Read<SparselyPopulatedArray<CancellationCallbackInfo>>(ref array[num]);
         if (sparselyPopulatedArray == null)
         {
             SparselyPopulatedArray<CancellationCallbackInfo> value = new SparselyPopulatedArray<CancellationCallbackInfo>(4);
             Interlocked.CompareExchange<SparselyPopulatedArray<CancellationCallbackInfo>>(ref array[num], value, null);
             sparselyPopulatedArray = array[num];
         }
         SparselyPopulatedArrayAddInfo<CancellationCallbackInfo> registrationInfo = sparselyPopulatedArray.Add(cancellationCallbackInfo);
         CancellationTokenRegistration result = new CancellationTokenRegistration(cancellationCallbackInfo, registrationInfo);
         if (!this.IsCancellationRequested)
         {
             return result;
         }
         if (!result.TryDeregister())
         {
             return result;
         }
     }
     callback(stateForCallback);
     return default(CancellationTokenRegistration);
 }
コード例 #23
0
ファイル: CancellationTokenSource.cs プロジェクト: rmc00/gsf
 internal void WaitForCallbackToComplete(CancellationCallbackInfo callbackInfo)
 {
     SpinWait spinWait = default(SpinWait);
     while (this.ExecutingCallback == callbackInfo)
     {
         spinWait.SpinOnce();
     }
 }
コード例 #24
0
ファイル: CancellationTokenSource.cs プロジェクト: rmc00/gsf
 private void ExecuteCallbackHandlers(bool throwOnFirstException)
 {
     List<Exception> list = null;
     SparselyPopulatedArray<CancellationCallbackInfo>[] registeredCallbacksLists = this.m_registeredCallbacksLists;
     if (registeredCallbacksLists == null)
     {
         Interlocked.Exchange(ref this.m_state, 3);
         return;
     }
     try
     {
         for (int i = 0; i < registeredCallbacksLists.Length; i++)
         {
             SparselyPopulatedArray<CancellationCallbackInfo> sparselyPopulatedArray = Volatile.Read<SparselyPopulatedArray<CancellationCallbackInfo>>(ref registeredCallbacksLists[i]);
             if (sparselyPopulatedArray != null)
             {
                 for (SparselyPopulatedArrayFragment<CancellationCallbackInfo> sparselyPopulatedArrayFragment = sparselyPopulatedArray.Tail; sparselyPopulatedArrayFragment != null; sparselyPopulatedArrayFragment = sparselyPopulatedArrayFragment.Prev)
                 {
                     for (int j = sparselyPopulatedArrayFragment.Length - 1; j >= 0; j--)
                     {
                         this.m_executingCallback = sparselyPopulatedArrayFragment[j];
                         if (this.m_executingCallback != null)
                         {
                             CancellationCallbackCoreWorkArguments cancellationCallbackCoreWorkArguments = new CancellationCallbackCoreWorkArguments(sparselyPopulatedArrayFragment, j);
                             try
                             {
                                 if (this.m_executingCallback.TargetSyncContext != null)
                                 {
                                     this.m_executingCallback.TargetSyncContext.Send(new SendOrPostCallback(this.CancellationCallbackCoreWork_OnSyncContext), cancellationCallbackCoreWorkArguments);
                                     this.ThreadIDExecutingCallbacks = Thread.CurrentThread.ManagedThreadId;
                                 }
                                 else
                                 {
                                     this.CancellationCallbackCoreWork(cancellationCallbackCoreWorkArguments);
                                 }
                             }
                             catch (Exception item)
                             {
                                 if (throwOnFirstException)
                                 {
                                     throw;
                                 }
                                 if (list == null)
                                 {
                                     list = new List<Exception>();
                                 }
                                 list.Add(item);
                             }
                         }
                     }
                 }
             }
         }
     }
     finally
     {
         this.m_state = 3;
         this.m_executingCallback = null;
         Thread.MemoryBarrier();
     }
     if (list != null)
     {
         throw new AggregateException(list);
     }
 }
コード例 #25
0
        /// <summary>
        /// Invoke the Canceled event.
        /// </summary>
        /// <remarks>
        /// The handlers are invoked synchronously in LIFO order.
        /// </remarks>
        private void ExecuteCallbackHandlers(bool throwOnFirstException)
        {
            Contract.Assert(IsCancellationRequested, "ExecuteCallbackHandlers should only be called after setting IsCancellationRequested->true");
            Contract.Assert(ThreadIDExecutingCallbacks != -1, "ThreadIDExecutingCallbacks should have been set.");

            // Design decision: call the delegates in LIFO order so that callbacks fire 'deepest first'.
            // This is intended to help with nesting scenarios so that child enlisters cancel before their parents.
            List <Exception> exceptionList = null;

            SparselyPopulatedArray <CancellationCallbackInfo>[] callbackLists = m_registeredCallbacksLists;

            // If there are no callbacks to run, we can safely exit.  Any races to lazy initialize it
            // will see IsCancellationRequested and will then run the callback themselves.
            if (callbackLists == null)
            {
                Interlocked.Exchange(ref m_state, NOTIFYINGCOMPLETE);
                return;
            }

            try
            {
                for (int index = 0; index < callbackLists.Length; index++)
                {
                    SparselyPopulatedArray <CancellationCallbackInfo> list = callbackLists[index];
                    if (list != null)
                    {
                        SparselyPopulatedArrayFragment <CancellationCallbackInfo> currArrayFragment = list.Tail;

                        while (currArrayFragment != null)
                        {
                            for (int i = currArrayFragment.Length - 1; i >= 0; i--)
                            {
                                // 1a. publish the indended callback, to ensure ctr.Dipose can tell if a wait is necessary.
                                // 1b. transition to the target syncContext and continue there..
                                //  On the target SyncContext.
                                //   2. actually remove the callback
                                //   3. execute the callback
                                // re:#2 we do the remove on the syncCtx so that we can be sure we have control of the syncCtx before
                                //        grabbing the callback.  This prevents a deadlock if ctr.Dispose() might run on the syncCtx too.
                                m_executingCallback = currArrayFragment[i];
                                if (m_executingCallback != null)
                                {
                                    //Transition to the target sync context (if necessary), and continue our work there.
                                    CancellationCallbackCoreWorkArguments args = new CancellationCallbackCoreWorkArguments(currArrayFragment, i);

                                    // marshal exceptions: either aggregate or perform an immediate rethrow
                                    // We assume that syncCtx.Send() has forwarded on user exceptions when appropriate.
                                    try
                                    {
                                        if (m_executingCallback.TargetSyncContext != null)
                                        {
                                            m_executingCallback.TargetSyncContext.Send(CancellationCallbackCoreWork_OnSyncContext, args);
                                            // CancellationCallbackCoreWork_OnSyncContext may have altered ThreadIDExecutingCallbacks, so reset it.
                                            ThreadIDExecutingCallbacks = Thread.CurrentThread.ManagedThreadId;
                                        }
                                        else
                                        {
                                            CancellationCallbackCoreWork_OnSyncContext(args);
                                        }
                                    }
                                    catch (Exception ex)
                                    {
                                        if (throwOnFirstException)
                                        {
                                            throw;
                                        }

                                        // Otherwise, log it and proceed.
                                        if (exceptionList == null)
                                        {
                                            exceptionList = new List <Exception>();
                                        }
                                        exceptionList.Add(ex);
                                    }
                                }
                            }

                            currArrayFragment = currArrayFragment.Prev;
                        }
                    }
                }
            }
            finally
            {
                m_state             = NOTIFYINGCOMPLETE;
                m_executingCallback = null;
                Thread.MemoryBarrier(); // for safety, prevent reorderings crossing this point and seeing inconsistent state.
            }

            if (exceptionList != null)
            {
                Contract.Assert(exceptionList.Count > 0, "Expected exception count > 0");
                throw new AggregateException(exceptionList);
            }
        }
 private void ExecuteCallbackHandlers(bool throwOnFirstException)
 {
     List<Exception> innerExceptions = null;
     SparselyPopulatedArray<CancellationCallbackInfo>[] registeredCallbacksLists = this.m_registeredCallbacksLists;
     if (registeredCallbacksLists == null)
     {
         Interlocked.Exchange(ref this.m_state, 3);
     }
     else
     {
         try
         {
             for (int i = 0; i < registeredCallbacksLists.Length; i++)
             {
                 SparselyPopulatedArray<CancellationCallbackInfo> array = registeredCallbacksLists[i];
                 if (array != null)
                 {
                     for (SparselyPopulatedArrayFragment<CancellationCallbackInfo> fragment = array.Tail; fragment != null; fragment = fragment.Prev)
                     {
                         for (int j = fragment.Length - 1; j >= 0; j--)
                         {
                             this.m_executingCallback = fragment[j];
                             if (this.m_executingCallback != null)
                             {
                                 CancellationCallbackCoreWorkArguments state = new CancellationCallbackCoreWorkArguments(fragment, j);
                                 try
                                 {
                                     if (this.m_executingCallback.TargetSyncContext != null)
                                     {
                                         this.m_executingCallback.TargetSyncContext.Send(new SendOrPostCallback(this.CancellationCallbackCoreWork_OnSyncContext), state);
                                         this.ThreadIDExecutingCallbacks = Thread.CurrentThread.ManagedThreadId;
                                     }
                                     else
                                     {
                                         this.CancellationCallbackCoreWork_OnSyncContext(state);
                                     }
                                 }
                                 catch (Exception exception)
                                 {
                                     if (throwOnFirstException)
                                     {
                                         throw;
                                     }
                                     if (innerExceptions == null)
                                     {
                                         innerExceptions = new List<Exception>();
                                     }
                                     innerExceptions.Add(exception);
                                 }
                             }
                         }
                     }
                 }
             }
         }
         finally
         {
             this.m_state = 3;
             this.m_executingCallback = null;
             Thread.MemoryBarrier();
         }
         if (innerExceptions != null)
         {
             throw new AggregateException(innerExceptions);
         }
     }
 }
 internal CancellationTokenRegistration InternalRegister(Action<object> callback, object stateForCallback, SynchronizationContext targetSyncContext, ExecutionContext executionContext)
 {
     this.ThrowIfDisposed();
     if (!this.IsCancellationRequested)
     {
         int index = Thread.CurrentThread.ManagedThreadId % s_nLists;
         CancellationCallbackInfo element = new CancellationCallbackInfo(callback, stateForCallback, targetSyncContext, executionContext, this);
         if (this.m_registeredCallbacksLists == null)
         {
             SparselyPopulatedArray<CancellationCallbackInfo>[] arrayArray = new SparselyPopulatedArray<CancellationCallbackInfo>[s_nLists];
             Interlocked.CompareExchange<SparselyPopulatedArray<CancellationCallbackInfo>[]>(ref this.m_registeredCallbacksLists, arrayArray, null);
         }
         if (this.m_registeredCallbacksLists[index] == null)
         {
             SparselyPopulatedArray<CancellationCallbackInfo> array = new SparselyPopulatedArray<CancellationCallbackInfo>(4);
             Interlocked.CompareExchange<SparselyPopulatedArray<CancellationCallbackInfo>>(ref this.m_registeredCallbacksLists[index], array, null);
         }
         SparselyPopulatedArrayAddInfo<CancellationCallbackInfo> registrationInfo = this.m_registeredCallbacksLists[index].Add(element);
         CancellationTokenRegistration registration = new CancellationTokenRegistration(this, element, registrationInfo);
         if (!this.IsCancellationRequested)
         {
             return registration;
         }
         if (!registration.TryDeregister())
         {
             this.WaitForCallbackToComplete(element);
             return new CancellationTokenRegistration();
         }
     }
     callback(stateForCallback);
     return new CancellationTokenRegistration();
 }
 internal void WaitForCallbackToComplete(CancellationCallbackInfo callbackInfo)
 {
     SpinWait wait = new SpinWait();
     while (this.ExecutingCallback == callbackInfo)
     {
         wait.SpinOnce();
     }
 }
コード例 #29
0
        private void ExecuteCallbackHandlers(bool throwOnFirstException)
        {
            List <Exception> list = null;

            SparselyPopulatedArray <CancellationCallbackInfo>[] registeredCallbacksLists = this.m_registeredCallbacksLists;
            if (registeredCallbacksLists == null)
            {
                Interlocked.Exchange(ref this.m_state, 3);
                return;
            }
            try
            {
                for (int i = 0; i < registeredCallbacksLists.Length; i++)
                {
                    SparselyPopulatedArray <CancellationCallbackInfo> sparselyPopulatedArray = Volatile.Read <SparselyPopulatedArray <CancellationCallbackInfo> >(ref registeredCallbacksLists[i]);
                    if (sparselyPopulatedArray != null)
                    {
                        for (SparselyPopulatedArrayFragment <CancellationCallbackInfo> sparselyPopulatedArrayFragment = sparselyPopulatedArray.Tail; sparselyPopulatedArrayFragment != null; sparselyPopulatedArrayFragment = sparselyPopulatedArrayFragment.Prev)
                        {
                            for (int j = sparselyPopulatedArrayFragment.Length - 1; j >= 0; j--)
                            {
                                this.m_executingCallback = sparselyPopulatedArrayFragment[j];
                                if (this.m_executingCallback != null)
                                {
                                    CancellationCallbackCoreWorkArguments cancellationCallbackCoreWorkArguments = new CancellationCallbackCoreWorkArguments(sparselyPopulatedArrayFragment, j);
                                    try
                                    {
                                        if (this.m_executingCallback.TargetSyncContext != null)
                                        {
                                            this.m_executingCallback.TargetSyncContext.Send(new SendOrPostCallback(this.CancellationCallbackCoreWork_OnSyncContext), cancellationCallbackCoreWorkArguments);
                                            this.ThreadIDExecutingCallbacks = Thread.CurrentThread.ManagedThreadId;
                                        }
                                        else
                                        {
                                            this.CancellationCallbackCoreWork(cancellationCallbackCoreWorkArguments);
                                        }
                                    }
                                    catch (Exception item)
                                    {
                                        if (throwOnFirstException)
                                        {
                                            throw;
                                        }
                                        if (list == null)
                                        {
                                            list = new List <Exception>();
                                        }
                                        list.Add(item);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            finally
            {
                this.m_state             = 3;
                this.m_executingCallback = null;
                Thread.MemoryBarrier();
            }
            if (list != null)
            {
                throw new AggregateException(list);
            }
        }
 internal CancellationTokenRegistration(CancellationTokenSource tokenSource, CancellationCallbackInfo callbackInfo, SparselyPopulatedArrayAddInfo <CancellationCallbackInfo> registrationInfo)
 {
     this.m_tokenSource      = tokenSource;
     this.m_callbackInfo     = callbackInfo;
     this.m_registrationInfo = registrationInfo;
 }