1 #include "dawn_native/AsyncTask.h" 2 3 #include "dawn_platform/DawnPlatform.h" 4 5 namespace dawn_native { 6 AsyncTaskManager(dawn_platform::WorkerTaskPool * workerTaskPool)7 AsyncTaskManager::AsyncTaskManager(dawn_platform::WorkerTaskPool* workerTaskPool) 8 : mWorkerTaskPool(workerTaskPool) { 9 } 10 PostTask(AsyncTask asyncTask)11 void AsyncTaskManager::PostTask(AsyncTask asyncTask) { 12 // If these allocations becomes expensive, we can slab-allocate tasks. 13 Ref<WaitableTask> waitableTask = AcquireRef(new WaitableTask()); 14 waitableTask->taskManager = this; 15 waitableTask->asyncTask = std::move(asyncTask); 16 17 { 18 // We insert new waitableTask objects into mPendingTasks in main thread (PostTask()), 19 // and we may remove waitableTask objects from mPendingTasks in either main thread 20 // (WaitAllPendingTasks()) or sub-thread (TaskCompleted), so mPendingTasks should be 21 // protected by a mutex. 22 std::lock_guard<std::mutex> lock(mPendingTasksMutex); 23 mPendingTasks.emplace(waitableTask.Get(), waitableTask); 24 } 25 26 // Ref the task since it is accessed inside the worker function. 27 // The worker function will acquire and release the task upon completion. 28 waitableTask->Reference(); 29 waitableTask->waitableEvent = 30 mWorkerTaskPool->PostWorkerTask(DoWaitableTask, waitableTask.Get()); 31 } 32 HandleTaskCompletion(WaitableTask * task)33 void AsyncTaskManager::HandleTaskCompletion(WaitableTask* task) { 34 std::lock_guard<std::mutex> lock(mPendingTasksMutex); 35 auto iter = mPendingTasks.find(task); 36 if (iter != mPendingTasks.end()) { 37 mPendingTasks.erase(iter); 38 } 39 } 40 WaitAllPendingTasks()41 void AsyncTaskManager::WaitAllPendingTasks() { 42 std::unordered_map<WaitableTask*, Ref<WaitableTask>> allPendingTasks; 43 44 { 45 std::lock_guard<std::mutex> lock(mPendingTasksMutex); 46 allPendingTasks.swap(mPendingTasks); 47 } 48 49 for (auto& keyValue : allPendingTasks) { 50 keyValue.second->waitableEvent->Wait(); 51 } 52 } 53 HasPendingTasks()54 bool AsyncTaskManager::HasPendingTasks() { 55 std::lock_guard<std::mutex> lock(mPendingTasksMutex); 56 return !mPendingTasks.empty(); 57 } 58 DoWaitableTask(void * task)59 void AsyncTaskManager::DoWaitableTask(void* task) { 60 Ref<WaitableTask> waitableTask = AcquireRef(static_cast<WaitableTask*>(task)); 61 waitableTask->asyncTask(); 62 waitableTask->taskManager->HandleTaskCompletion(waitableTask.Get()); 63 } 64 65 } // namespace dawn_native 66