internal SparselyPopulatedArrayAddInfo(SparselyPopulatedArrayFragment <T> source, int index)
 {
     Contract.Assert(source != null);
     Contract.Assert(index >= 0 && index < source.Length);
     m_source = source;
     m_index  = index;
 }
        // Token: 0x06003E4F RID: 15951 RVA: 0x000E7788 File Offset: 0x000E5988
        internal SparselyPopulatedArrayAddInfo <T> Add(T element)
        {
            SparselyPopulatedArrayFragment <T> sparselyPopulatedArrayFragment2;
            int num2;

            for (;;)
            {
                SparselyPopulatedArrayFragment <T> sparselyPopulatedArrayFragment = this.m_tail;
                while (sparselyPopulatedArrayFragment.m_next != null)
                {
                    sparselyPopulatedArrayFragment = (this.m_tail = sparselyPopulatedArrayFragment.m_next);
                }
                for (sparselyPopulatedArrayFragment2 = sparselyPopulatedArrayFragment; sparselyPopulatedArrayFragment2 != null; sparselyPopulatedArrayFragment2 = sparselyPopulatedArrayFragment2.m_prev)
                {
                    if (sparselyPopulatedArrayFragment2.m_freeCount < 1)
                    {
                        sparselyPopulatedArrayFragment2.m_freeCount--;
                    }
                    if (sparselyPopulatedArrayFragment2.m_freeCount > 0 || sparselyPopulatedArrayFragment2.m_freeCount < -10)
                    {
                        int length = sparselyPopulatedArrayFragment2.Length;
                        int num    = (length - sparselyPopulatedArrayFragment2.m_freeCount) % length;
                        if (num < 0)
                        {
                            num = 0;
                            sparselyPopulatedArrayFragment2.m_freeCount--;
                        }
                        for (int i = 0; i < length; i++)
                        {
                            num2 = (num + i) % length;
                            if (sparselyPopulatedArrayFragment2.m_elements[num2] == null && Interlocked.CompareExchange <T>(ref sparselyPopulatedArrayFragment2.m_elements[num2], element, default(T)) == null)
                            {
                                goto Block_5;
                            }
                        }
                    }
                }
                SparselyPopulatedArrayFragment <T> sparselyPopulatedArrayFragment3 = new SparselyPopulatedArrayFragment <T>((sparselyPopulatedArrayFragment.m_elements.Length == 4096) ? 4096 : (sparselyPopulatedArrayFragment.m_elements.Length * 2), sparselyPopulatedArrayFragment);
                if (Interlocked.CompareExchange <SparselyPopulatedArrayFragment <T> >(ref sparselyPopulatedArrayFragment.m_next, sparselyPopulatedArrayFragment3, null) == null)
                {
                    this.m_tail = sparselyPopulatedArrayFragment3;
                }
            }
Block_5:
            int num3 = sparselyPopulatedArrayFragment2.m_freeCount - 1;

            sparselyPopulatedArrayFragment2.m_freeCount = ((num3 > 0) ? num3 : 0);
            return(new SparselyPopulatedArrayAddInfo <T>(sparselyPopulatedArrayFragment2, num2));
        }
 internal SparselyPopulatedArrayAddInfo <T> Add(T element)
 {
     while (true)
     {
         SparselyPopulatedArrayFragment <T> tail = this.m_tail;
         while (tail.m_next != null)
         {
             this.m_tail = tail = tail.m_next;
         }
         for (SparselyPopulatedArrayFragment <T> fragment2 = tail; fragment2 != null; fragment2 = fragment2.m_prev)
         {
             if (fragment2.m_freeCount < 1)
             {
                 fragment2.m_freeCount--;
             }
             if ((fragment2.m_freeCount > 0) || (fragment2.m_freeCount < -10))
             {
                 int length = fragment2.Length;
                 int num2   = (length - fragment2.m_freeCount) % length;
                 if (num2 < 0)
                 {
                     num2 = 0;
                     fragment2.m_freeCount--;
                 }
                 for (int i = 0; i < length; i++)
                 {
                     int index = (num2 + i) % length;
                     if (fragment2.m_elements[index] == null)
                     {
                         T comparand = default(T);
                         if (Interlocked.CompareExchange <T>(ref fragment2.m_elements[index], element, comparand) == null)
                         {
                             int num5 = fragment2.m_freeCount - 1;
                             fragment2.m_freeCount = (num5 > 0) ? num5 : 0;
                             return(new SparselyPopulatedArrayAddInfo <T>(fragment2, index));
                         }
                     }
                 }
             }
         }
         SparselyPopulatedArrayFragment <T> fragment3 = new SparselyPopulatedArrayFragment <T>((tail.m_elements.Length == 0x1000) ? 0x1000 : (tail.m_elements.Length * 2), tail);
         if (Interlocked.CompareExchange <SparselyPopulatedArrayFragment <T> >(ref tail.m_next, fragment3, null) == null)
         {
             this.m_tail = fragment3;
         }
     }
 }
 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);
 }
Esempio n. 5
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);
                }
            }
        }
 internal SparselyPopulatedArrayAddInfo(SparselyPopulatedArrayFragment <T> source, int index)
 {
     this.m_source = source;
     this.m_index  = index;
 }
 internal SparselyPopulatedArrayFragment(int size, SparselyPopulatedArrayFragment <T> prev)
 {
     m_elements  = new T[size];
     m_freeCount = size;
     m_prev      = prev;
 }
        /// <summary>
        /// Adds an element in the first available slot, beginning the search from the tail-to-head.
        /// If no slots are available, the array is grown.  The method doesn't return until successful.
        /// </summary>
        /// <param name="element">The element to add.</param>
        /// <returns>Information about where the add happened, to enable O(1) deregistration.</returns>
        internal SparselyPopulatedArrayAddInfo <T> Add(T element)
        {
            while (true)
            {
                // Get the tail, and ensure it's up to date.
                SparselyPopulatedArrayFragment <T> tail = m_tail;
                while (tail.m_next != null)
                {
                    m_tail = (tail = tail.m_next);
                }

                // Search for a free index, starting from the tail.
                SparselyPopulatedArrayFragment <T> curr = tail;
                while (curr != null)
                {
                    const int RE_SEARCH_THRESHOLD = -10; // Every 10 skips, force a search.
                    if (curr.m_freeCount < 1)
                    {
                        --curr.m_freeCount;
                    }

                    if (curr.m_freeCount > 0 || curr.m_freeCount < RE_SEARCH_THRESHOLD)
                    {
                        int c = curr.Length;

                        // We'll compute a start offset based on how many free slots we think there
                        // are.  This optimizes for ordinary the LIFO deregistration pattern, and is
                        // far from perfect due to the non-threadsafe ++ and -- of the free counter.
                        int start = ((c - curr.m_freeCount) % c);
                        if (start < 0)
                        {
                            start = 0;
                            curr.m_freeCount--; // Too many free elements; fix up.
                        }
                        Contract.Assert(start >= 0 && start < c, "start is outside of bounds");

                        // Now walk the array until we find a free slot (or reach the end).
                        for (int i = 0; i < c; i++)
                        {
                            // If the slot is null, try to CAS our element into it.
                            int tryIndex = (start + i) % c;
                            Contract.Assert(tryIndex >= 0 && tryIndex < curr.m_elements.Length, "tryIndex is outside of bounds");

                            if (curr.m_elements[tryIndex] == null && Interlocked.CompareExchange(ref curr.m_elements[tryIndex], element, null) == null)
                            {
                                // We adjust the free count by --. Note: if this drops to 0, we will skip
                                // the fragment on the next search iteration.  Searching threads will -- the
                                // count and force a search every so often, just in case fragmentation occurs.
                                int newFreeCount = curr.m_freeCount - 1;
                                curr.m_freeCount = newFreeCount > 0 ? newFreeCount : 0;
                                return(new SparselyPopulatedArrayAddInfo <T>(curr, tryIndex));
                            }
                        }
                    }

                    curr = curr.m_prev;
                }

                // If we got here, we need to add a new chunk to the tail and try again.
                SparselyPopulatedArrayFragment <T> newTail = new SparselyPopulatedArrayFragment <T>(
                    tail.m_elements.Length == 4096 ? 4096 : tail.m_elements.Length * 2, tail);
                if (Interlocked.CompareExchange(ref tail.m_next, newTail, null) == null)
                {
                    m_tail = newTail;
                }
            }
        }
 /// <summary>
 /// Allocates a new array with the given initial size.
 /// </summary>
 /// <param name="initialSize">How many array slots to pre-allocate.</param>
 internal SparselyPopulatedArray(int initialSize)
 {
     m_head = m_tail = new SparselyPopulatedArrayFragment <T>(initialSize);
 }
 public CancellationCallbackCoreWorkArguments(SparselyPopulatedArrayFragment <CancellationCallbackInfo> currArrayFragment, int currArrayIndex)
 {
     m_currArrayFragment = currArrayFragment;
     m_currArrayIndex    = currArrayIndex;
 }
        /// <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);
            }
        }
Esempio n. 12
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);
            }
        }
        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);
                }
            }
        }