/// <summary> /// The dispatch loop run by each thread in the scheduler. /// </summary> private void DispatchLoop() { WorkStealingQueue <Task> workStealingQueue = new WorkStealingQueue <Task>(); WorkStealingTaskScheduler.m_wsq = workStealingQueue; this.AddWsq(workStealingQueue); try { while (true) { Task task = null; if (!workStealingQueue.LocalPop(ref task)) { bool flag = false; while (true) { lock (this.m_queue) { if (this.m_shutdown) { return; } if (this.m_queue.Count != 0) { task = this.m_queue.Dequeue(); break; } if (flag) { this.m_threadsWaiting++; try { Monitor.Wait(this.m_queue); } finally { this.m_threadsWaiting--; } if (this.m_shutdown) { return; } flag = false; continue; } } WorkStealingQueue <Task>[] wsQueues = this.m_wsQueues; int i; for (i = 0; i < wsQueues.Length; i++) { WorkStealingQueue <Task> workStealingQueue2 = wsQueues[i]; if (workStealingQueue2 != null && workStealingQueue2 != workStealingQueue && workStealingQueue2.TrySteal(ref task)) { break; } } if (i != wsQueues.Length) { break; } flag = true; } } base.TryExecuteTask(task); } } finally { this.RemoveWsq(workStealingQueue); } }
/// <summary> /// The dispatch loop run by each thread in the scheduler. /// </summary> private void DispatchLoop() { // Create a new queue for this thread, store it in TLS for later retrieval, // and add it to the set of queues for this scheduler. WorkStealingQueue <Task> wsq = new WorkStealingQueue <Task>(); m_wsq = wsq; AddWsq(wsq); try { // Until there's no more work to do... while (true) { Task wi = null; // Search order: (1) local WSQ, (2) global Q, (3) steals from other queues. if (!wsq.LocalPop(ref wi)) { // We weren't able to get a task from the local WSQ bool searchedForSteals = false; while (true) { lock (m_queue) { // If shutdown was requested, exit the thread. if (m_shutdown) { return; } // (2) try the global queue. if (m_queue.Count != 0) { // We found a work item! Grab it ... wi = m_queue.Dequeue(); break; } else if (searchedForSteals) { // Note that we're not waiting for work, and then wait m_threadsWaiting++; try { Monitor.Wait(m_queue); } finally { m_threadsWaiting--; } // If we were signaled due to shutdown, exit the thread. if (m_shutdown) { return; } searchedForSteals = false; continue; } } // (3) try to steal. WorkStealingQueue <Task>[] wsQueues = m_wsQueues; int i; for (i = 0; i < wsQueues.Length; i++) { WorkStealingQueue <Task> q = wsQueues[i]; if (q != null && q != wsq && q.TrySteal(ref wi)) { break; } } if (i != wsQueues.Length) { break; } searchedForSteals = true; } } // ...and Invoke it. TryExecuteTask(wi); } } finally { RemoveWsq(wsq); } }