• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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