ttg 1.0.0
Template Task Graph (TTG): flowgraph-based programming model for high-performance distributed-memory algorithms
Loading...
Searching...
No Matches
coroutine.h
Go to the documentation of this file.
1// SPDX-License-Identifier: BSD-3-Clause
2//
3// Created by Eduard Valeyev on 10/31/22.
4//
5
6#ifndef TTG_COROUTINE_H
7#define TTG_COROUTINE_H
8
9#include "ttg/config.h"
10
11#ifdef TTG_HAVE_COROUTINE
12#include TTG_CXX_COROUTINE_HEADER
13
14#include <algorithm>
15#include <array>
16
17
18namespace ttg {
19
20 // import std coroutine API into ttg namespace
21
22 using suspend_always = TTG_CXX_COROUTINE_NAMESPACE::suspend_always;
23 using suspend_never = TTG_CXX_COROUTINE_NAMESPACE::suspend_never;
24 template <typename Promise>
25 using coroutine_handle = TTG_CXX_COROUTINE_NAMESPACE::coroutine_handle<Promise>;
26
28
32
34
35 // fwd-declares
36
38
39 template <std::size_t N>
41
43 struct event {
44 void finish() { finished_ = true; }
45
47 bool finished() const { return finished_; }
48
49 private:
50 std::atomic<bool> finished_ = false;
51 };
52
54 struct resumable_task : public ttg::coroutine_handle<resumable_task_state> {
56
59
61
63
64 resumable_task(base_type base) : base_type(std::move(base)) {}
65
66 base_type handle() { return *this; }
67
69 inline bool ready() const;
70
72 inline bool completed() const;
73
75 inline ttg::span<event*> events();
76 };
77
81 resumable_task_state() noexcept = default;
82 // these only live on coroutine frames so make noncopyable and nonmovable
84 resumable_task_state& operator=(const resumable_task_state&) = delete;
87
88 constexpr static inline std::size_t MaxNumEvents = 20;
90
93
94 resumable_task get_return_object() { return resumable_task{handle_type::from_promise(*this)}; }
95
97 suspend_never initial_suspend() noexcept { return {}; }
98
101 completed_ = true;
102 return {};
103 }
104 void return_void() {}
106
108
111
112 // these can be used to use optional storage provided by the runtime (e.g. part of the runtime's task data struct)
113 // N.B. the existing buffer must be passed to operator new via TLS
114 // void* operator new(std::size_t size)
115 // {
116 // return ::operator new(size);
117 // }
118
119 // N.B. whether the external buffer was used by operator new must be passed via TLS
120 // void operator delete(void* ptr, std::size_t size)
121 // {
122 // ::operator delete(ptr, size);
123 // }
124
126
128 constexpr bool ready() const {
129 for (std::size_t e = 0; e != nevents_; ++e)
130 if (!events_storage_[e]->finished()) return false;
131 return true;
132 }
133
135 constexpr bool completed() const { return completed_; }
136
137 ttg::span<event*> events() { return ttg::span(events_storage_.data(), nevents_); }
138
139 private:
140 std::array<event*, MaxNumEvents> events_storage_;
141 std::size_t nevents_;
142 bool completed_ = false;
143
144 template <std::size_t N>
146
147 void reset_events() {
148 std::fill(events_storage_.begin(), events_storage_.begin() + nevents_, nullptr);
149 nevents_ = 0;
150 }
151
152 template <std::size_t N>
153 void set_events(const std::array<event*, N> events) {
154 static_assert(N <= MaxNumEvents);
155 std::copy(events.begin(), events.end(), events_storage_.begin());
156 nevents_ = N;
157 }
158 };
159
160 bool resumable_task::ready() const { return base_type::promise().ready(); }
161 bool resumable_task::completed() const { return base_type::promise().completed(); }
162 ttg::span<event*> resumable_task::events() { return base_type::promise().events(); }
163
168 template <std::size_t N>
170 private:
171 template <std::size_t... I>
172 constexpr bool await_ready(std::index_sequence<I...>) const {
173 return (std::get<I>(events_)->finished() && ...);
174 }
175
176 public:
177 template <typename... Events>
178 constexpr resumable_task_events(Events&&... events) : events_{(&events)...} {}
179
182
183 constexpr bool await_ready() const { return await_ready(std::make_index_sequence<N>{}); }
184
186 pending_task_ = pending_task;
187 pending_task_.promise().set_events(events_);
188 }
189
191 if (pending_task_) {
192 pending_task_.promise().reset_events();
193 pending_task_ = {};
194 }
195 }
196
198
199 private:
200 std::array<event*, N> events_;
202 }; // resumable_task_events
203
204 // deduce the number of events properly
205 template <typename... Events>
206 resumable_task_events(Events&&...) -> resumable_task_events<sizeof...(Events)>;
207
208 static_assert(resumable_task_events<0>{}.await_ready() == true);
209
211
213 // describe all types of coroutine tasks known to TTG
215
216 // fwd declare all coro promise types that have not been declared yet
217 namespace device::detail {
218 struct device_task_promise_type;
219 } // namespace device::detail
220
223 enum class TaskCoroutineID {
225 Invalid,
230 };
231
232} // namespace ttg
233
234#endif // TTG_HAVE_COROUTINE
235
236#endif // TTG_COROUTINE_H
bool ready() const
Definition coroutine.h:160
ttg::span< event * > events()
Definition coroutine.h:162
bool completed() const
Definition coroutine.h:161
STL namespace.
top-level TTG namespace contains runtime-neutral functionality
Definition keymap.h:9
TTG_CXX_COROUTINE_NAMESPACE::suspend_always suspend_always
Definition coroutine.h:22
TTG_CXX_COROUTINE_NAMESPACE::suspend_never suspend_never
Definition coroutine.h:23
TTG_CXX_COROUTINE_NAMESPACE::coroutine_handle< Promise > coroutine_handle
Definition coroutine.h:25
TaskCoroutineID
Definition coroutine.h:223
@ ResumableTask
-> ttg::resumable_task
@ Invalid
not a coroutine, i.e. a standard task function, -> void
@ DeviceTask
-> ttg::device::Task
represents a generic one-time event
Definition coroutine.h:43
bool finished() const
Definition coroutine.h:47
void finish()
Definition coroutine.h:44
constexpr bool await_ready() const
Definition coroutine.h:183
constexpr resumable_task_events(Events &&... events)
Definition coroutine.h:178
void await_suspend(coroutine_handle< resumable_task_state > pending_task)
Definition coroutine.h:185
constexpr bool completed() const
Definition coroutine.h:135
resumable_task get_return_object()
Definition coroutine.h:94
resumable_task_state() noexcept=default
static constexpr std::size_t MaxNumEvents
Definition coroutine.h:88
constexpr bool ready() const
Definition coroutine.h:128
suspend_always final_suspend() noexcept
Definition coroutine.h:100
ttg::span< event * > events()
Definition coroutine.h:137
suspend_never initial_suspend() noexcept
Definition coroutine.h:97
coroutine_handle< resumable_task_state > handle_type
Definition coroutine.h:89
task that can be resumed after some events occur
Definition coroutine.h:54
resumable_task(base_type base)
Definition coroutine.h:64
ttg::coroutine_handle< resumable_task_state > base_type
Definition coroutine.h:55
base_type handle()
Definition coroutine.h:66