/// <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());
        }
 internal CancellationTokenRegistration(
     CancellationCallbackInfo callbackInfo,
     SparselyPopulatedArrayAddInfo <CancellationCallbackInfo> registrationInfo)
 {
     m_callbackInfo     = callbackInfo;
     m_registrationInfo = registrationInfo;
 }
 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());
 }
 // 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));
 }
 public bool Equals(CancellationTokenRegistration other)
 {
     if (this.m_callbackInfo == other.m_callbackInfo)
     {
         SparselyPopulatedArrayFragment <CancellationCallbackInfo> source1 = this.m_registrationInfo.Source;
         SparselyPopulatedArrayAddInfo <CancellationCallbackInfo>  populatedArrayAddInfo = other.m_registrationInfo;
         SparselyPopulatedArrayFragment <CancellationCallbackInfo> source2 = populatedArrayAddInfo.Source;
         if (source1 == source2)
         {
             populatedArrayAddInfo = this.m_registrationInfo;
             int index1 = populatedArrayAddInfo.Index;
             populatedArrayAddInfo = other.m_registrationInfo;
             int index2 = populatedArrayAddInfo.Index;
             return(index1 == index2);
         }
     }
     return(false);
 }
Example #6
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());
 }
 internal CancellationTokenRegistration(CancellationTokenSource tokenSource, CancellationCallbackInfo callbackInfo, SparselyPopulatedArrayAddInfo <CancellationCallbackInfo> registrationInfo)
 {
     this.m_tokenSource      = tokenSource;
     this.m_callbackInfo     = callbackInfo;
     this.m_registrationInfo = registrationInfo;
 }