public bool TryDequeue(ThreadPoolWorkQueueThreadLocals tl, out WorkItem workItem) { WorkStealingQueue localWsq = tl.workStealingQueue; if ((workItem = localWsq.LocalPop()) == null && // first try the local queue !workItems.TryDequeue(out workItem)) // then try the global queue { // finally try to steal from another thread's local queue WorkStealingQueue[] queues = tl.workQueue.workStealingQueues.Queues; int c = queues.Length; Debug.Assert(c > 0, "There must at least be a queue for this thread."); int maxIndex = c - 1; int i = tl.random.Next(c); while (c > 0) { i = (i < maxIndex) ? i + 1 : 0; WorkStealingQueue otherQueue = queues[i]; if (otherQueue != localWsq && otherQueue.CanSteal) { var ignoredMissedSteal = false; workItem = otherQueue.TrySteal(ref ignoredMissedSteal); if (workItem != null) { break; } } c--; } } return workItem != null; }
public void Enqueue(WorkItem callback, bool forceGlobal) { ThreadPoolWorkQueueThreadLocals tl = null; if (!forceGlobal) tl = ThreadPoolWorkQueueThreadLocals.threadLocals; if (null != tl && tl.workQueue == this) { tl.workStealingQueue.LocalPush(callback); } else { workItems.Enqueue(callback); } EnsureThreadRequested(); }
internal bool LocalFindAndPop(WorkItem callback) { ThreadPoolWorkQueueThreadLocals tl = ThreadPoolWorkQueueThreadLocals.threadLocals; return tl != null && tl.workStealingQueue.LocalFindAndPop(callback); }