unsigned int __stdcall TaskSchedulerImpl::WorkerProc(void* userdata) { unsigned int workerID = *static_cast<unsigned int*>(userdata); SetEvent(s_doneEvents[workerID]); Worker& worker = s_workers[workerID]; WaitForSingleObject(worker.wakeEvent, INFINITE); while (worker.running) { Functor* task = nullptr; if (worker.workCount > 0) // Permet d'éviter d'entrer inutilement dans une section critique { EnterCriticalSection(&worker.queueMutex); if (!worker.queue.empty()) // Nécessaire car le workCount peut être tombé à zéro juste avant l'entrée dans la section critique { task = worker.queue.front(); worker.queue.pop(); worker.workCount = worker.queue.size(); } LeaveCriticalSection(&worker.queueMutex); } // Que faire quand vous n'avez plus de travail ? if (!task) task = StealTask(workerID); // Voler le travail des autres ! if (task) { // On exécute la tâche avant de la supprimer task->Run(); delete task; } else { SetEvent(s_doneEvents[workerID]); WaitForSingleObject(worker.wakeEvent, INFINITE); } } // Au cas où un thread attendrait sur WaitForTasks() pendant qu'un autre appellerait Uninitialize() // Ça ne devrait pas arriver, mais comme ça ne coûte pas grand chose.. SetEvent(s_doneEvents[workerID]); return 0; }
void WorkerThread::DoTasks() { ThreadTask* task = 0; do { //Process any tasks in our queue while (task = PopTask()) { task->Run(); delete task; } //We ran out of tasks, so try to see if we can steal one task = StealTask(); if (task) { task->Run(); delete task; } } while (task); }