blob: 84f8764b23470d9e9f2854995a92a1dfecb66c69 [file] [log] [blame]
Jiawei Shao5d398602021-05-27 00:49:03 +00001#include "dawn_native/AsyncTask.h"
2
3#include "dawn_platform/DawnPlatform.h"
4
5namespace dawn_native {
6
Jiawei Shao5e1ca532021-06-04 05:12:06 +00007 AsyncTaskManager::AsyncTaskManager(dawn_platform::WorkerTaskPool* workerTaskPool)
Jiawei Shao5d398602021-05-27 00:49:03 +00008 : mWorkerTaskPool(workerTaskPool) {
9 }
10
Jiawei Shao5e1ca532021-06-04 05:12:06 +000011 void AsyncTaskManager::PostTask(AsyncTask asyncTask) {
Jiawei Shao5d398602021-05-27 00:49:03 +000012 // 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
Jiawei Shao5e1ca532021-06-04 05:12:06 +000033 void AsyncTaskManager::HandleTaskCompletion(WaitableTask* task) {
Jiawei Shao5d398602021-05-27 00:49:03 +000034 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
Jiawei Shao5e1ca532021-06-04 05:12:06 +000041 void AsyncTaskManager::WaitAllPendingTasks() {
Jiawei Shao5d398602021-05-27 00:49:03 +000042 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
Jiawei Shao5e1ca532021-06-04 05:12:06 +000054 bool AsyncTaskManager::HasPendingTasks() {
55 std::lock_guard<std::mutex> lock(mPendingTasksMutex);
56 return !mPendingTasks.empty();
57 }
58
59 void AsyncTaskManager::DoWaitableTask(void* task) {
Jiawei Shao5d398602021-05-27 00:49:03 +000060 Ref<WaitableTask> waitableTask = AcquireRef(static_cast<WaitableTask*>(task));
61 waitableTask->asyncTask();
62 waitableTask->taskManager->HandleTaskCompletion(waitableTask.Get());
63 }
64
65} // namespace dawn_native