Fenix @develop
 
Loading...
Searching...
No Matches
task.hpp
1#ifndef FENIX_TASKS_TASK_HPP
2#define FENIX_TASKS_TASK_HPP
3
4#include <cassert>
5#include <memory>
6
7#include "fenix/tasks/promise.hpp"
8#include "fenix/tasks/forward.hpp"
9
10namespace fenix::tasks {
11
12// WARNING: eager tasks can cause gross double free errors, due to some
13// early wonkiness in the C++ spec and in compiler implementations
14template <typename T, bool eager /*= false*/>
15class [[nodiscard("Must wait/await tasks")]] Task {
16 public:
18 using TaskT = Task<T, eager>;
19 using promise_type = PromiseT;
21 PromiseHolder() = delete;
22 PromiseHolder(PromiseT* p) : promise(p) {
23 promise->register_owning_ptr(&promise);
24 }
26 if (promise) promise->destroy();
27 }
28 PromiseT* operator->() { return promise; }
29 PromiseT* promise;
30 };
31
32 Task() = default;
33 Task(PromiseT* p) : prom(std::make_shared<PromiseHolder>(p)) {};
34
35 // Copy and move support
36 TaskT& operator=(const TaskT& o) {
37 prom = o.prom;
38 return *this;
39 }
40 TaskT& operator=(TaskT&& o) {
41 *this = o;
42 TaskT t{};
43 o = t;
44 return *this;
45 }
46 Task(const TaskT& o) { *this = o; };
47 Task(TaskT&& o) noexcept { *this = std::move(o); };
48
49 operator bool() const { return (bool)prom; };
50
51 bool done() const { return promise().done(); }
52 virtual void resume() { promise().resume(); }
53 virtual void wait() { promise().wait(); }
54
55 auto result() {
56 this->wait();
57 if constexpr (!std::is_same_v<T, void>) {
58 return promise().result();
59 }
60 }
61
62 private:
63 mutable std::shared_ptr<PromiseHolder> prom;
64 PromiseT& promise() const {
65 assert(prom);
66 return *(prom->promise);
67 }
68};
69
70template <typename T>
71using LazyTask = Task<T, false>;
72
73} // namespace fenix::tasks
74
75#endif // FENIX_TASKS_TASK_HPP
Definition promise.hpp:33
Definition task.hpp:15
Definition task.hpp:20