internal void Start() { thread = Thread.CurrentThread; CurrentTaskScheduler = this; while (!stopRequested) { Task w = queuedTasks.Pop(); if (w == null) { TaskScheduler other = next; while (other != this) { w = other.Steal(); if (w != null) { break; } other = other.next; } if (w == null) { if (!ThreadScheduler.StealDeque(this)) { stopped = true; CurrentTaskScheduler = null; return; } else { continue; } } } // w should not be null at this point w.RunTask(); } // end while(!stopRequested) // we have been stopped ThreadScheduler.AddTasks(queuedTasks); stopped = true; CurrentTaskScheduler = null; }
internal static bool StealDeque(TaskScheduler tsStealer) { lock (dequeLock) { if (queuedTasks.Empty) return false; else { // swap deques Deque<Task> tmp = tsStealer.QueuedTasks; tsStealer.QueuedTasks = queuedTasks; queuedTasks = tmp; return true; } } }
internal static void Start() { while (true) { int numThreads = 0; int numBlockedThreads = 0; int numStopRequested = 0; bool anyQueuedTasks = false; if (last != null) { // this is a little messy, but must work for 1 or more threads. TaskScheduler cur = last.Next; TaskScheduler prev = last; bool done = false; while (!done) { if (cur == last) // is this the last iteration? done = true; if (cur.IsStopped) { if (cur == prev) // there's only one thread { last = null; break; } else { // remove cur, prev does not change prev.Next = cur.Next; if (cur == last) // we're removing the last thread { last = prev; } } } else { numThreads++; if (cur.Thread != null && (cur.Thread.ThreadState & ThreadState.WaitSleepJoin) == ThreadState.WaitSleepJoin) { numBlockedThreads++; } if (!cur.QueuedTasks.Empty) anyQueuedTasks = true; if (cur.StopRequested) { numStopRequested++; } if (numThreads - numBlockedThreads - numStopRequested > numCores) { numStopRequested++; cur.StopRequested = true; } prev = cur; } cur = cur.Next; } } int numRunningThreads = numThreads - numBlockedThreads; if (numCores > numRunningThreads) { if (!queuedTasks.Empty || anyQueuedTasks) { int numNewScheds = numCores - numRunningThreads; for (int i = 0; i < numNewScheds; i++) CreateTaskScheduler(); } else if (numThreads == 0) { Monitor.Enter(dequeLock); if (queuedTasks.Empty) { waiting = true; Monitor.Wait(dequeLock); Monitor.Exit(dequeLock); } else { Monitor.Exit(dequeLock); for (int i = 0; i < numCores; i++) CreateTaskScheduler(); } } } Timer.SleepFor(sleepTime); } }
private static void CreateTaskScheduler() { TaskScheduler ts = new TaskScheduler(); if (last == null) // we have no TaskSchedulers { last = ts; // we make it point to itself ts.Next = ts; } else { ts.Next = last.Next; last.Next = ts; last = ts; } if (!queuedTasks.Empty) StealDeque(ts); JibuThreadPool.runTask(ts.Start); }