internal static void QueueWorkItem(IThreadPoolWorkItem item)
 {
     ThreadPool.QueueUserWorkItem
         (
             _ =>
             {
                 try
                 {
                     item.ExecuteWorkItem();
                 }
                 catch (ThreadAbortException exception)
                 {
                     item.MarkAborted(exception);
                 }
             }
         );
 }
Beispiel #2
0
 internal static bool TryPopCustomWorkItem(IThreadPoolWorkItem workItem)
 {
     return(false);
 }
Beispiel #3
0
        internal static void Dispatch()
        {
            var workQueue = ThreadPoolGlobals.workQueue;

            //
            // The clock is ticking!  We have ThreadPoolGlobals.tpQuantum milliseconds to get some work done, and then
            // we need to return to the VM.
            //
            int quantumStartTime = Environment.TickCount;

            //
            // Update our records to indicate that an outstanding request for a thread has now been fulfilled.
            // From this point on, we are responsible for requesting another thread if we stop working for any
            // reason, and we believe there might still be work in the queue.
            //
            workQueue.MarkThreadRequestSatisfied();

            //
            // Assume that we're going to need another thread if this one returns to the VM.  We'll set this to
            // false later, but only if we're absolutely certain that the queue is empty.
            //
            bool needAnotherThread       = true;
            IThreadPoolWorkItem workItem = null;

            try
            {
                //
                // Set up our thread-local data
                //
                ThreadPoolWorkQueueThreadLocals tl = workQueue.EnsureCurrentThreadHasQueue();

                //
                // Loop until our quantum expires.
                //
                while ((Environment.TickCount - quantumStartTime) < tpQuantum)
                {
                    bool missedSteal = false;
                    workQueue.Dequeue(tl, out workItem, out missedSteal);

                    if (workItem == null)
                    {
                        //
                        // No work.  We're going to return to the VM once we leave this protected region.
                        // If we missed a steal, though, there may be more work in the queue.
                        // Instead of looping around and trying again, we'll just request another thread.  This way
                        // we won't starve other AppDomains while we spin trying to get locks, and hopefully the thread
                        // that owns the contended work-stealing queue will pick up its own workitems in the meantime,
                        // which will be more efficient than this thread doing it anyway.
                        //
                        needAnotherThread = missedSteal;
                        return;
                    }

                    //
                    // If we found work, there may be more work.  Ask for another thread so that the other work can be processed
                    // in parallel.  Note that this will only ask for a max of #procs threads, so it's safe to call it for every dequeue.
                    //
                    workQueue.EnsureThreadRequested();

                    try
                    {
                        SynchronizationContext.SetSynchronizationContext(null);
                        workItem.ExecuteWorkItem();
                    }
                    finally
                    {
                        workItem = null;
                        SynchronizationContext.SetSynchronizationContext(null);
                    }
                }
            }
            catch (Exception e)
            {
                // Work items should not allow exceptions to escape.  For example, Task catches and stores any exceptions.
                Environment.FailFast("Unhandled exception in ThreadPool dispatch loop", e);
            }
            finally
            {
                //
                // If we are exiting for any reason other than that the queue is definitely empty, ask for another
                // thread to pick up where we left off.
                //
                if (needAnotherThread)
                {
                    workQueue.EnsureThreadRequested();
                }
            }
        }
Beispiel #4
0
            public bool LocalPop(out IThreadPoolWorkItem obj)
            {
                while (true)
                {
                    // Decrement the tail using a fence to ensure subsequent read doesn't come before.
                    int tail = m_tailIndex;
                    if (m_headIndex >= tail)
                    {
                        obj = null;
                        return(false);
                    }

                    tail -= 1;
                    Interlocked.Exchange(ref m_tailIndex, tail);

                    // If there is no interaction with a take, we can head down the fast path.
                    if (m_headIndex <= tail)
                    {
                        int idx = tail & m_mask;
                        obj = Volatile.Read(ref m_array[idx]);

                        // Check for nulls in the array.
                        if (obj == null)
                        {
                            continue;
                        }

                        m_array[idx] = null;
                        return(true);
                    }
                    else
                    {
                        // Interaction with takes: 0 or 1 elements left.
                        bool lockTaken = false;
                        try
                        {
                            m_foreignLock.Enter(ref lockTaken);

                            if (m_headIndex <= tail)
                            {
                                // Element still available. Take it.
                                int idx = tail & m_mask;
                                obj = Volatile.Read(ref m_array[idx]);

                                // Check for nulls in the array.
                                if (obj == null)
                                {
                                    continue;
                                }

                                m_array[idx] = null;
                                return(true);
                            }
                            else
                            {
                                // We lost the race, element was stolen, restore the tail.
                                m_tailIndex = tail + 1;
                                obj         = null;
                                return(false);
                            }
                        }
                        finally
                        {
                            if (lockTaken)
                            {
                                m_foreignLock.Exit(false);
                            }
                        }
                    }
                }
            }
Beispiel #5
0
            public void LocalPush(IThreadPoolWorkItem obj)
            {
                int tail = m_tailIndex;

                // We're going to increment the tail; if we'll overflow, then we need to reset our counts
                if (tail == int.MaxValue)
                {
                    bool lockTaken = false;
                    try
                    {
                        m_foreignLock.Enter(ref lockTaken);

                        if (m_tailIndex == int.MaxValue)
                        {
                            //
                            // Rather than resetting to zero, we'll just mask off the bits we don't care about.
                            // This way we don't need to rearrange the items already in the queue; they'll be found
                            // correctly exactly where they are.  One subtlety here is that we need to make sure that
                            // if head is currently < tail, it remains that way.  This happens to just fall out from
                            // the bit-masking, because we only do this if tail == int.MaxValue, meaning that all
                            // bits are set, so all of the bits we're keeping will also be set.  Thus it's impossible
                            // for the head to end up > than the tail, since you can't set any more bits than all of
                            // them.
                            //
                            m_headIndex = m_headIndex & m_mask;
                            m_tailIndex = tail = m_tailIndex & m_mask;
                            Debug.Assert(m_headIndex <= m_tailIndex);
                        }
                    }
                    finally
                    {
                        if (lockTaken)
                        {
                            m_foreignLock.Exit(true);
                        }
                    }
                }

                // When there are at least 2 elements' worth of space, we can take the fast path.
                if (tail < m_headIndex + m_mask)
                {
                    Volatile.Write(ref m_array[tail & m_mask], obj);
                    m_tailIndex = tail + 1;
                }
                else
                {
                    // We need to contend with foreign pops, so we lock.
                    bool lockTaken = false;
                    try
                    {
                        m_foreignLock.Enter(ref lockTaken);

                        int head  = m_headIndex;
                        int count = m_tailIndex - m_headIndex;

                        // If there is still space (one left), just add the element.
                        if (count >= m_mask)
                        {
                            // We're full; expand the queue by doubling its size.
                            IThreadPoolWorkItem[] newArray = new IThreadPoolWorkItem[m_array.Length << 1];
                            for (int i = 0; i < m_array.Length; i++)
                            {
                                newArray[i] = m_array[(i + head) & m_mask];
                            }

                            // Reset the field values, incl. the mask.
                            m_array     = newArray;
                            m_headIndex = 0;
                            m_tailIndex = tail = count;
                            m_mask      = (m_mask << 1) | 1;
                        }

                        Volatile.Write(ref m_array[tail & m_mask], obj);
                        m_tailIndex = tail + 1;
                    }
                    finally
                    {
                        if (lockTaken)
                        {
                            m_foreignLock.Exit(false);
                        }
                    }
                }
            }
Beispiel #6
0
        /// <summary>
        /// Dispatches work items to this thread.
        /// </summary>
        /// <returns>
        /// <c>true</c> if this thread did as much work as was available or its quantum expired.
        /// <c>false</c> if this thread stopped working early.
        /// </returns>
        internal static bool Dispatch()
        {
            var workQueue = ThreadPoolGlobals.workQueue;

            //
            // Save the start time
            //
            int startTickCount = Environment.TickCount;

            //
            // Update our records to indicate that an outstanding request for a thread has now been fulfilled.
            // From this point on, we are responsible for requesting another thread if we stop working for any
            // reason, and we believe there might still be work in the queue.
            //
            workQueue.MarkThreadRequestSatisfied();

            Interlocked.Increment(ref workQueue.numWorkingThreads);

            //
            // Assume that we're going to need another thread if this one returns to the VM.  We'll set this to
            // false later, but only if we're absolutely certain that the queue is empty.
            //
            bool needAnotherThread       = true;
            IThreadPoolWorkItem workItem = null;

            try
            {
                //
                // Set up our thread-local data
                //
                ThreadPoolWorkQueueThreadLocals tl = workQueue.EnsureCurrentThreadHasQueue();

                //
                // Loop until our quantum expires or there is no work.
                //
                while (ThreadPool.KeepDispatching(startTickCount))
                {
                    bool missedSteal = false;
                    workItem = workQueue.Dequeue(tl, ref missedSteal);

                    if (workItem == null)
                    {
                        //
                        // No work.
                        // If we missed a steal, though, there may be more work in the queue.
                        // Instead of looping around and trying again, we'll just request another thread.  Hopefully the thread
                        // that owns the contended work-stealing queue will pick up its own workitems in the meantime,
                        // which will be more efficient than this thread doing it anyway.
                        //
                        needAnotherThread = missedSteal;

                        // Tell the VM we're returning normally, not because Hill Climbing asked us to return.
                        return(true);
                    }

                    //
                    // If we found work, there may be more work.  Ask for another thread so that the other work can be processed
                    // in parallel.  Note that this will only ask for a max of #procs threads, so it's safe to call it for every dequeue.
                    //
                    workQueue.EnsureThreadRequested();

                    try
                    {
                        SynchronizationContext.SetSynchronizationContext(null);
                        workItem.ExecuteWorkItem();
                    }
                    finally
                    {
                        workItem = null;
                        SynchronizationContext.SetSynchronizationContext(null);
                    }

                    RuntimeThread.CurrentThread.ResetThreadPoolThread();

                    if (!ThreadPool.NotifyWorkItemComplete())
                    {
                        return(false);
                    }
                }

                // If we get here, it's because our quantum expired.
                return(true);
            }
            catch (Exception e)
            {
                // Work items should not allow exceptions to escape.  For example, Task catches and stores any exceptions.
                Environment.FailFast("Unhandled exception in ThreadPool dispatch loop", e);
                return(true); // Will never actually be executed because Environment.FailFast doesn't return
            }
            finally
            {
                int numWorkers = Interlocked.Decrement(ref workQueue.numWorkingThreads);
                Debug.Assert(numWorkers >= 0);

                //
                // If we are exiting for any reason other than that the queue is definitely empty, ask for another
                // thread to pick up where we left off.
                //
                if (needAnotherThread)
                {
                    workQueue.EnsureThreadRequested();
                }
            }
        }
Beispiel #7
0
 // This method tries to take the target callback out of the current thread's queue.
 internal static bool TryPopCustomWorkItem(IThreadPoolWorkItem workItem)
 {
     Debug.Assert(null != workItem);
     return(ThreadPoolGlobals.workQueue.LocalFindAndPop(workItem));
 }
Beispiel #8
0
        static internal void Dispatch()
        {
            var workQueue = ThreadPoolGlobals.workQueue;

            //
            // The clock is ticking!  We have ThreadPoolGlobals.tpQuantum milliseconds to get some work done, and then
            // we need to return to the VM.
            //
            int quantumStartTime = Environment.TickCount;

            //
            // Update our records to indicate that an outstanding request for a thread has now been fulfilled.
            // From this point on, we are responsible for requesting another thread if we stop working for any
            // reason, and we believe there might still be work in the queue.
            //
            // Note that if this thread is aborted before we get a chance to request another one, the VM will
            // record a thread request on our behalf.  So we don't need to worry about getting aborted right here.
            //
            workQueue.MarkThreadRequestSatisfied();

#if !FEATURE_CORECLR
            // Has the desire for logging changed since the last time we entered?
            //workQueue.loggingEnabled = System.Diagnostics.Tracing.FrameworkEventSource.Log.IsEnabled(System.Diagnostics.Tracing.EventLevel.Verbose, System.Diagnostics.Tracing.FrameworkEventSource.Keywords.ThreadPool);
#endif

            //
            // Assume that we're going to need another thread if this one returns to the VM.  We'll set this to
            // false later, but only if we're absolutely certain that the queue is empty.
            //
            bool needAnotherThread       = true;
            IThreadPoolWorkItem workItem = null;
            try
            {
                //
                // Set up our thread-local data
                //
                ThreadPoolWorkQueueThreadLocals tl = workQueue.EnsureCurrentThreadHasQueue();

                //
                // Loop until our quantum expires.
                //
                while ((Environment.TickCount - quantumStartTime) < tpQuantum)
                {
                    //
                    // Dequeue and EnsureThreadRequested must be protected from ThreadAbortException.
                    // These are fast, so this will not delay aborts/AD-unloads for very long.
                    //
                    try { }
                    finally
                    {
                        bool missedSteal = false;
                        workQueue.Dequeue(tl, out workItem, out missedSteal);

                        if (workItem == null)
                        {
                            //
                            // No work.  We're going to return to the VM once we leave this protected region.
                            // If we missed a steal, though, there may be more work in the queue.
                            // Instead of looping around and trying again, we'll just request another thread.  This way
                            // we won't starve other AppDomains while we spin trying to get locks, and hopefully the thread
                            // that owns the contended work-stealing queue will pick up its own workitems in the meantime,
                            // which will be more efficient than this thread doing it anyway.
                            //
                            needAnotherThread = missedSteal;
                        }
                        else
                        {
                            //
                            // If we found work, there may be more work.  Ask for another thread so that the other work can be processed
                            // in parallel.  Note that this will only ask for a max of #procs threads, so it's safe to call it for every dequeue.
                            //
                            workQueue.EnsureThreadRequested();
                        }
                    }

                    if (workItem == null)
                    {
                        // no more work to do
                        return;
                    }
                    else
                    {
#if !FEATURE_CORECLR
                        //if (workQueue.loggingEnabled)
                        //    System.Diagnostics.Tracing.FrameworkEventSource.Log.ThreadPoolDequeueWorkObject(workItem);
#endif

                        //
                        // Execute the workitem outside of any finally blocks, so that it can be aborted if needed.
                        //
                        //RuntimeHelpers.PrepareConstrainedRegions();
                        try
                        {
                            SynchronizationContext.SetSynchronizationContext(null);
                            workItem.ExecuteWorkItem();
                        }
                        finally
                        {
                            workItem = null;
                            SynchronizationContext.SetSynchronizationContext(null);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                // Work items should not allow exceptions to escape.  For example, Task catches and stores any exceptions.
                Environment.FailFast("Unhandled exception in ThreadPool dispatch loop", e);
            }
            finally
            {
                //
                // If we are exiting for any reason other than that the queue is definitely empty, ask for another
                // thread to pick up where we left off.
                //
                if (needAnotherThread)
                {
                    workQueue.EnsureThreadRequested();
                }
            }
        }
 internal static bool TryPopCustomWorkItem(IThreadPoolWorkItem workItem)
 {
     if (!ThreadPoolGlobals.vmTpInitialized)
     {
         return false;
     }
     return ThreadPoolGlobals.workQueue.LocalFindAndPop(workItem);
 }
Beispiel #10
0
 public static bool TryPopCustomWorkItem(IThreadPoolWorkItem workItem) => false;
Beispiel #11
0
 public static void UnsafeQueueCustomWorkItem(IThreadPoolWorkItem workItem, bool forceGlobal)
 {
     java.lang.Runnable.Delegate runnable = () => workItem.ExecuteWorkItem();
     JavaThreadPool.execute(runnable.AsInterface());
 }
Beispiel #12
0
		internal static bool TryPopCustomWorkItem(IThreadPoolWorkItem workItem)
		{
			return false;
		}
Beispiel #13
0
		// Extracted from ../../../../external/referencesource/mscorlib/system/threading/threadpool.cs
		internal static void UnsafeQueueCustomWorkItem(IThreadPoolWorkItem workItem, bool forceGlobal)
		{
			QueueWorkItem ((obj) => ((IThreadPoolWorkItem)obj).ExecuteWorkItem (), workItem);
		}
Beispiel #14
0
        internal static bool Dispatch()
        {
            bool flag4;
            int  tickCount = Environment.TickCount;

            ThreadPoolGlobals.workQueue.MarkThreadRequestSatisfied();
            bool flag = true;
            IThreadPoolWorkItem callback = null;

            try
            {
                ThreadPoolWorkQueueThreadLocals tl = ThreadPoolGlobals.workQueue.EnsureCurrentThreadHasQueue();
                while ((Environment.TickCount - tickCount) < ThreadPoolGlobals.tpQuantum)
                {
                    try
                    {
                    }
                    finally
                    {
                        bool missedSteal = false;
                        ThreadPoolGlobals.workQueue.Dequeue(tl, out callback, out missedSteal);
                        if (callback == null)
                        {
                            flag = missedSteal;
                        }
                        else
                        {
                            ThreadPoolGlobals.workQueue.EnsureThreadRequested();
                        }
                    }
                    if (callback == null)
                    {
                        return(true);
                    }
                    if (ThreadPoolGlobals.enableWorkerTracking)
                    {
                        bool flag3 = false;
                        try
                        {
                            try
                            {
                            }
                            finally
                            {
                                ThreadPool.ReportThreadStatus(true);
                                flag3 = true;
                            }
                            callback.ExecuteWorkItem();
                            callback = null;
                        }
                        finally
                        {
                            if (flag3)
                            {
                                ThreadPool.ReportThreadStatus(false);
                            }
                        }
                    }
                    else
                    {
                        callback.ExecuteWorkItem();
                        callback = null;
                    }
                    if (!ThreadPool.NotifyWorkItemComplete())
                    {
                        return(false);
                    }
                }
                flag4 = true;
            }
            catch (ThreadAbortException exception)
            {
                if (callback != null)
                {
                    callback.MarkAborted(exception);
                }
                flag = false;
                throw;
            }
            finally
            {
                if (flag)
                {
                    ThreadPoolGlobals.workQueue.EnsureThreadRequested();
                }
            }
            return(flag4);
        }
Beispiel #15
0
            public void LocalPush(IThreadPoolWorkItem obj)
            {
                int tailIndex = this.m_tailIndex;

                if (tailIndex == 0x7fffffff)
                {
                    bool lockTaken = false;
                    try
                    {
                        this.m_foreignLock.Enter(ref lockTaken);
                        if (this.m_tailIndex == 0x7fffffff)
                        {
                            this.m_headIndex &= this.m_mask;
                            this.m_tailIndex  = tailIndex = this.m_tailIndex & this.m_mask;
                        }
                    }
                    finally
                    {
                        if (lockTaken)
                        {
                            this.m_foreignLock.Exit(true);
                        }
                    }
                }
                if (tailIndex < (this.m_headIndex + this.m_mask))
                {
                    this.m_array[tailIndex & this.m_mask] = obj;
                    this.m_tailIndex = tailIndex + 1;
                }
                else
                {
                    bool flag2 = false;
                    try
                    {
                        this.m_foreignLock.Enter(ref flag2);
                        int headIndex = this.m_headIndex;
                        int num3      = this.m_tailIndex - this.m_headIndex;
                        if (num3 >= this.m_mask)
                        {
                            IThreadPoolWorkItem[] itemArray = new IThreadPoolWorkItem[this.m_array.Length << 1];
                            for (int i = 0; i < this.m_array.Length; i++)
                            {
                                itemArray[i] = this.m_array[(i + headIndex) & this.m_mask];
                            }
                            this.m_array     = itemArray;
                            this.m_headIndex = 0;
                            this.m_tailIndex = tailIndex = num3;
                            this.m_mask      = (this.m_mask << 1) | 1;
                        }
                        this.m_array[tailIndex & this.m_mask] = obj;
                        this.m_tailIndex = tailIndex + 1;
                    }
                    finally
                    {
                        if (flag2)
                        {
                            this.m_foreignLock.Exit(false);
                        }
                    }
                }
            }
Beispiel #16
0
		// Extracted from ../../../../external/referencesource/mscorlib/system/threading/threadpool.cs
		internal static void UnsafeQueueCustomWorkItem(IThreadPoolWorkItem workItem, bool forceGlobal)
		{
			if (Microsoft.ThreadPool.UseMicrosoftThreadPool)
				Microsoft.ThreadPool.UnsafeQueueCustomWorkItem (workItem, forceGlobal);
			else
				QueueWorkItem ((obj) => ((IThreadPoolWorkItem)obj).ExecuteWorkItem (), workItem);
		}
Beispiel #17
0
		internal static bool TryPopCustomWorkItem(IThreadPoolWorkItem workItem)
		{
			if (Microsoft.ThreadPool.UseMicrosoftThreadPool)
				return Microsoft.ThreadPool.TryPopCustomWorkItem (workItem);
			else
				return false;
		}
 internal static void UnsafeQueueCustomWorkItem(IThreadPoolWorkItem workItem, bool forceGlobal)
 {
     EnsureVMInitialized();
     try
     {
     }
     finally
     {
         ThreadPoolGlobals.workQueue.Enqueue(workItem, forceGlobal);
     }
 }
 /// <inheritdoc/>
 bool IWorkItemDispatcher.Dispatch(out IThreadPoolWorkItem item, CancellationToken cancellationToken)
 {
     // с такими параметрами TryTake вернёт false только если операцию отменили.
     return(blockingCollection.TryTake(out item, Timeout.Infinite, cancellationToken));
 }
Beispiel #20
0
 public static bool UnsafeQueueUserWorkItem(IThreadPoolWorkItem callBack, bool preferLocal) => throw new NotImplementedException();
Beispiel #21
0
        internal bool LocalFindAndPop(IThreadPoolWorkItem callback)
        {
            ThreadPoolWorkQueueThreadLocals tl = ThreadPoolWorkQueueThreadLocals.threadLocals;

            return(tl != null && tl.workStealingQueue.LocalFindAndPop(callback));
        }
        internal static bool Dispatch()
        {
            ThreadPoolWorkQueue workQueue = ThreadPoolGlobals.workQueue;
            int tickCount = Environment.TickCount;

            workQueue.MarkThreadRequestSatisfied();
            workQueue.loggingEnabled = FrameworkEventSource.Log.IsEnabled(EventLevel.Verbose, (EventKeywords)18L);
            bool flag = true;
            IThreadPoolWorkItem threadPoolWorkItem = null;

            try
            {
                ThreadPoolWorkQueueThreadLocals tl = workQueue.EnsureCurrentThreadHasQueue();
                while ((long)(Environment.TickCount - tickCount) < (long)((ulong)ThreadPoolGlobals.tpQuantum))
                {
                    try
                    {
                    }
                    finally
                    {
                        bool flag2 = false;
                        workQueue.Dequeue(tl, out threadPoolWorkItem, out flag2);
                        if (threadPoolWorkItem == null)
                        {
                            flag = flag2;
                        }
                        else
                        {
                            workQueue.EnsureThreadRequested();
                        }
                    }
                    if (threadPoolWorkItem == null)
                    {
                        return(true);
                    }
                    if (workQueue.loggingEnabled)
                    {
                        FrameworkEventSource.Log.ThreadPoolDequeueWorkObject(threadPoolWorkItem);
                    }
                    if (ThreadPoolGlobals.enableWorkerTracking)
                    {
                        bool flag3 = false;
                        try
                        {
                            try
                            {
                            }
                            finally
                            {
                                ThreadPool.ReportThreadStatus(true);
                                flag3 = true;
                            }
                            threadPoolWorkItem.ExecuteWorkItem();
                            threadPoolWorkItem = null;
                            goto IL_A6;
                        }
                        finally
                        {
                            if (flag3)
                            {
                                ThreadPool.ReportThreadStatus(false);
                            }
                        }
                        goto IL_9E;
                    }
                    goto IL_9E;
IL_A6:
                    if (!ThreadPool.NotifyWorkItemComplete())
                    {
                        return(false);
                    }
                    continue;
IL_9E:
                    threadPoolWorkItem.ExecuteWorkItem();
                    threadPoolWorkItem = null;
                    goto IL_A6;
                }
                return(true);
            }
            catch (ThreadAbortException tae)
            {
                if (threadPoolWorkItem != null)
                {
                    threadPoolWorkItem.MarkAborted(tae);
                }
                flag = false;
            }
            finally
            {
                if (flag)
                {
                    workQueue.EnsureThreadRequested();
                }
            }
            return(true);
        }
Beispiel #23
0
 // This method tries to take the target callback out of the current thread's queue.
 internal static bool TryPopCustomWorkItem(IThreadPoolWorkItem workItem)
 {
     return(ThreadPoolGlobals.workQueue.LocalFindAndPop(workItem));
 }
            // Token: 0x06006E44 RID: 28228 RVA: 0x0017B4D4 File Offset: 0x001796D4
            public bool LocalPop(out IThreadPoolWorkItem obj)
            {
                int num3;

                for (;;)
                {
                    int num = this.m_tailIndex;
                    if (this.m_headIndex >= num)
                    {
                        break;
                    }
                    num--;
                    Interlocked.Exchange(ref this.m_tailIndex, num);
                    if (this.m_headIndex > num)
                    {
                        bool flag = false;
                        bool result;
                        try
                        {
                            this.m_foreignLock.Enter(ref flag);
                            if (this.m_headIndex <= num)
                            {
                                int num2 = num & this.m_mask;
                                obj = Volatile.Read <IThreadPoolWorkItem>(ref this.m_array[num2]);
                                if (obj == null)
                                {
                                    continue;
                                }
                                this.m_array[num2] = null;
                                result             = true;
                            }
                            else
                            {
                                this.m_tailIndex = num + 1;
                                obj    = null;
                                result = false;
                            }
                        }
                        finally
                        {
                            if (flag)
                            {
                                this.m_foreignLock.Exit(false);
                            }
                        }
                        return(result);
                    }
                    num3 = (num & this.m_mask);
                    obj  = Volatile.Read <IThreadPoolWorkItem>(ref this.m_array[num3]);
                    if (obj != null)
                    {
                        goto Block_2;
                    }
                }
                obj = null;
                return(false);

Block_2:
                this.m_array[num3] = null;
                return(true);
            }
Beispiel #25
0
            public bool LocalFindAndPop(IThreadPoolWorkItem obj)
            {
                // Fast path: check the tail. If equal, we can skip the lock.
                if (m_array[(m_tailIndex - 1) & m_mask] == obj)
                {
                    IThreadPoolWorkItem unused;
                    if (LocalPop(out unused))
                    {
                        Debug.Assert(unused == obj);
                        return(true);
                    }
                    return(false);
                }

                // Else, do an O(N) search for the work item. The theory of work stealing and our
                // inlining logic is that most waits will happen on recently queued work.  And
                // since recently queued work will be close to the tail end (which is where we
                // begin our search), we will likely find it quickly.  In the worst case, we
                // will traverse the whole local queue; this is typically not going to be a
                // problem (although degenerate cases are clearly an issue) because local work
                // queues tend to be somewhat shallow in length, and because if we fail to find
                // the work item, we are about to block anyway (which is very expensive).
                for (int i = m_tailIndex - 2; i >= m_headIndex; i--)
                {
                    if (m_array[i & m_mask] == obj)
                    {
                        // If we found the element, block out steals to avoid interference.
                        // @TODO: optimize away the lock?
                        bool lockTaken = false;
                        try
                        {
                            m_foreignLock.Enter(ref lockTaken);

                            // If we lost the race, bail.
                            if (m_array[i & m_mask] == null)
                            {
                                return(false);
                            }

                            // Otherwise, null out the element.
                            Volatile.Write(ref m_array[i & m_mask], null);

                            // And then check to see if we can fix up the indexes (if we're at
                            // the edge).  If we can't, we just leave nulls in the array and they'll
                            // get filtered out eventually (but may lead to superflous resizing).
                            if (i == m_tailIndex)
                            {
                                m_tailIndex -= 1;
                            }
                            else if (i == m_headIndex)
                            {
                                m_headIndex += 1;
                            }

                            return(true);
                        }
                        finally
                        {
                            if (lockTaken)
                            {
                                m_foreignLock.Exit(false);
                            }
                        }
                    }
                }

                return(false);
            }
 // Token: 0x06006E45 RID: 28229 RVA: 0x0017B5D0 File Offset: 0x001797D0
 public bool TrySteal(out IThreadPoolWorkItem obj, ref bool missedSteal)
 {
     return(this.TrySteal(out obj, ref missedSteal, 0));
 }
Beispiel #27
0
 public bool TrySteal(out IThreadPoolWorkItem obj, ref bool missedSteal)
 {
     return(TrySteal(out obj, ref missedSteal, 0)); // no blocking by default.
 }
Beispiel #28
0
 private static void RunThreadPoolWorkItemTask(IThreadPoolWorkItem todo)
 {
     todo.Execute();
 }
Beispiel #29
0
 internal static void UnsafeQueueCustomWorkItem(IThreadPoolWorkItem workItem, bool forceGlobal)
 {
     Debug.Assert(null != workItem);
     ThreadPoolGlobals.workQueue.Enqueue(workItem, forceGlobal);
 }
Beispiel #30
0
 // Extracted from ../../../../external/referencesource/mscorlib/system/threading/threadpool.cs
 internal static void UnsafeQueueCustomWorkItem(IThreadPoolWorkItem workItem, bool forceGlobal)
 {
     QueueWorkItem((obj) => ((IThreadPoolWorkItem)obj).ExecuteWorkItem(), workItem);
 }