Squid::Tasks 1.0.0
C++14 coroutine-based task library for games
TaskManager.h
1#pragma once
2
78
79#include <vector>
80
81#include "Task.h"
82
83NAMESPACE_SQUID_BEGIN
84
85//--- TaskManager ---//
88{
89public:
90 ~TaskManager() {}
91
95 template <typename tRet>
96 SQUID_NODISCARD TaskHandle<tRet> Run(Task<tRet>&& in_task)
97 {
98 // Run unmanaged task
99 TaskHandle<tRet> taskHandle = in_task;
100 WeakTask weakTask = std::move(in_task);
101 RunWeakTask(std::move(weakTask));
102 return taskHandle;
103 }
104 template <typename tRet>
105 SQUID_NODISCARD TaskHandle<tRet> Run(const Task<tRet>& in_task)
106 {
107 static_assert(static_false<tRet>::value, "Cannot run an unmanaged task by copy (try Run(std::move(task)))");
108 return {};
109 }
110
114 template <typename tRet>
116 {
117 // Run managed task
118 WeakTaskHandle weakTaskHandle = in_task;
119 m_strongRefs.push_back(Run(std::move(in_task)));
120 return weakTaskHandle;
121 }
122 template <typename tRet>
123 WeakTaskHandle RunManaged(const Task<tRet>& in_task)
124 {
125 static_assert(static_false<tRet>::value, "Cannot run a managed task by copy (try RunManaged(std::move(task)))");
126 return {};
127 }
128
133 void RunWeakTask(WeakTask&& in_task)
134 {
135 // Run unmanaged task
136 m_tasks.push_back(std::move(in_task));
137 }
138
141 {
142 m_tasks.clear(); // Destroying all the weak tasks implicitly destroys all internal tasks
143
144 // No need to call Kill() on each TaskHandle in m_strongRefs
145 m_strongRefs.clear(); // Handles in the strong refs array only ever point to tasks in the now-cleared m_tasks array
146 }
147
151 {
152 // Request stop on all tasks
153 std::vector<WeakTaskHandle> weakHandles;
154 for(auto& task : m_tasks)
155 {
156 task.RequestStop();
157 weakHandles.push_back(task);
158 }
159
160 // Return a fence task that waits until all stopped tasks are complete
161 return [](std::vector<WeakTaskHandle> in_weakHandles) -> Task<> {
162 TASK_NAME("StopAllTasks() Fence Task");
163 for(const auto& weakHandle : in_weakHandles)
164 {
165 co_await weakHandle; // Wait until task is complete
166 }
167 }(std::move(weakHandles));
168 }
169
171 void Update()
172 {
173 // Resume all tasks
174 size_t writeIdx = 0;
175 for(size_t readIdx = 0; readIdx < m_tasks.size(); ++readIdx)
176 {
177 if(m_tasks[readIdx].Resume() != eTaskStatus::Done)
178 {
179 if(writeIdx != readIdx)
180 {
181 m_tasks[writeIdx] = std::move(m_tasks[readIdx]);
182 }
183 ++writeIdx;
184 }
185 }
186 m_tasks.resize(writeIdx);
187
188 // Prune strong tasks that are done
189 auto removeIt = m_strongRefs.erase(std::remove_if(m_strongRefs.begin(), m_strongRefs.end(), [](const auto& in_taskHandle) {
190 return in_taskHandle.IsDone();
191 }), m_strongRefs.end());
192 }
193
195 std::string GetDebugString(std::optional<TaskDebugStackFormatter> in_formatter = {}) const
196 {
197 std::string debugStr;
198 for(const auto& task : m_tasks)
199 {
200 if(!task.IsDone())
201 {
202 if(debugStr.size())
203 {
204 debugStr += '\n';
205 }
206 debugStr += task.GetDebugStack(in_formatter);
207 }
208 }
209 return debugStr;
210 }
211
212private:
213 std::vector<WeakTask> m_tasks;
214 std::vector<TaskHandle<>> m_strongRefs;
215};
216
217NAMESPACE_SQUID_END
218
Definition: Task.h:204
void RequestStop()
Issues a request for the task to terminate gracefully as soon as possible.
Definition: Task.h:289
Manager that runs and resumes a collection of tasks.
Definition: TaskManager.h:88
WeakTaskHandle RunManaged(Task< tRet > &&in_task)
Run a managed task.
Definition: TaskManager.h:115
void KillAllTasks()
Call Task::Kill() on all tasks (managed + unmanaged)
Definition: TaskManager.h:140
TaskHandle< tRet > Run(Task< tRet > &&in_task)
Destructor (disables copy/move construction + assignment)
Definition: TaskManager.h:96
void RunWeakTask(WeakTask &&in_task)
Run a weak task.
Definition: TaskManager.h:133
Task StopAllTasks()
Issue a stop request using Task::RequestStop() on all active tasks (managed and unmanaged)
Definition: TaskManager.h:150
void Update()
Call Task::Resume() on all active tasks exactly once (managed + unmanaged)
Definition: TaskManager.h:171
std::string GetDebugString(std::optional< TaskDebugStackFormatter > in_formatter={}) const
Get a debug string containing a list of all active tasks.
Definition: TaskManager.h:195
#define TASK_NAME(...)
Macro that instruments a task with a debug name string. Usually at the top of every task coroutine as...
Definition: Task.h:25
@ Done
Task has terminated and coroutine frame has been destroyed.