MayaFlux 0.1.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Awaiters.hpp
Go to the documentation of this file.
1#pragma once
2
5
6namespace MayaFlux::Vruta {
7class EventSource;
8}
9
10namespace MayaFlux::Kriya {
11
12/**
13 * @struct SampleDelay
14 * @brief Awaitable object for precise sample-accurate timing delays
15 *
16 * SampleDelay is the primary timing mechanism in the computational coroutine system.
17 * When a coroutine co_awaits a SampleDelay, it suspends execution until
18 * exactly the specified number of discrete time units (samples) have been processed.
19 *
20 * This provides deterministic timing for computational events, which is essential
21 * for applications where precise temporal relationships are critical. Unlike
22 * system-time-based delays which can drift due to processing load, SampleDelay guarantees
23 * that operations occur at exact positions in the discrete time continuum.
24 *
25 * Example usage:
26 * ```cpp
27 * // Wait for exactly 4410 time units (100ms at 44.1kHz sample rate)
28 * co_await SampleDelay{4410};
29 * ```
30 *
31 * SampleDelay is the foundation for all timing in the computational engine, enabling
32 * precise sequencing, modulation, and synchronization of events across multiple domains
33 * (signal processing, visual rendering, data transformation, physical modeling, etc.).
34 */
35struct MAYAFLUX_API SampleDelay {
36 /**
37 * @brief Type alias for the coroutine promise type
38 *
39 * This alias simplifies references to the Vruta::promise_type
40 * throughout the Kriya namespace.
41 */
43
44 /**
45 * @brief Number of time units to wait before resuming the coroutine
46 *
47 * This value is added to the coroutine's next_sample field when
48 * await_suspend is called, scheduling the coroutine to resume
49 * after exactly this many discrete time units have been processed.
50 */
52
53 SampleDelay(uint64_t samples)
54 : samples_to_wait(samples)
55 {
56 }
57
58 /**
59 * @brief Checks if the delay should be bypassed
60 * @return True if no delay is needed, false otherwise
61 *
62 * If samples_to_wait is 0, the coroutine continues execution
63 * without suspending. This optimization avoids the overhead
64 * of suspension for zero-length delays.
65 */
66 [[nodiscard]] inline bool await_ready() const { return samples_to_wait == 0; }
67
68 /**
69 * @brief Called when the coroutine is resumed after the delay
70 *
71 * This method is called when the scheduler resumes the coroutine
72 * after the specified delay. It doesn't need to do anything since
73 * the delay itself is the only effect needed.
74 */
75 inline void await_resume() { };
76
77 /**
78 * @brief Schedules the coroutine to resume after the delay
79 * @param h Handle to the suspended coroutine
80 *
81 * This method is called when the coroutine suspends. It updates
82 * the coroutine's next_sample field to schedule it for resumption
83 * after the specified number of time units have been processed.
84 */
85 void await_suspend(std::coroutine_handle<promise_handle> h) noexcept;
86};
87
88/**
89 * @struct BufferDelay
90 * @brief Awaiter for suspending until a buffer cycle boundary
91 *
92 * Works identically to SampleDelay but at buffer cycle granularity.
93 * Accumulates cycles in promise.next_buffer_cycle.
94 *
95 * **Usage:**
96 * ```cpp
97 * auto routine = []() -> SoundRoutine {
98 * while (true) {
99 * process_buffer();
100 * co_await BufferDelay{2}; // Resume every 2 buffer cycles
101 * }
102 * };
103 * ```
104 */
105struct MAYAFLUX_API BufferDelay {
106 /**
107 * @brief Type alias for the coroutine promise type
108 *
109 * This alias simplifies references to the Vruta::promise_type
110 * throughout the Kriya namespace.
111 */
113
114 BufferDelay(uint64_t cycles)
115 : num_cycles(cycles)
116 {
117 }
118
119 uint64_t num_cycles;
120
121 [[nodiscard]] constexpr bool await_ready() const noexcept { return num_cycles == 0; }
122
123 void await_suspend(std::coroutine_handle<promise_handle> h) noexcept
124 {
125 auto& promise = h.promise();
126 promise.next_buffer_cycle += num_cycles;
127 promise.delay_amount = num_cycles;
128 promise.active_delay_context = Vruta::DelayContext::BUFFER_BASED;
129 }
130
131 constexpr void await_resume() const noexcept { }
132};
133
134/**
135 * @struct FrameDelay
136 * @brief graphics-domain awaiter for frame-accurate timing delays
137 *
138 * Future awaiter for visual processing routines that operate at frame rates.
139 * This will work with visual_promise types that have next_frame fields.
140 */
141struct MAYAFLUX_API FrameDelay {
142 /**
143 * @brief Type alias for the coroutine promise type
144 *
145 * This alias simplifies references to the Vruta::promise_type
146 * throughout the Kriya namespace.
147 */
149
151
152 [[nodiscard]] constexpr bool await_ready() const noexcept
153 {
154 return frames_to_wait == 0;
155 }
156
157 constexpr void await_resume() const noexcept { }
158
159 void await_suspend(std::coroutine_handle<Vruta::graphics_promise> h) noexcept;
160};
161
162struct MAYAFLUX_API MultiRateDelay {
163
166
167 [[nodiscard]] constexpr bool await_ready() const noexcept
168 {
169 return samples_to_wait == 0 && frames_to_wait == 0;
170 }
171
172 constexpr void await_resume() const noexcept { }
173
174 void await_suspend(std::coroutine_handle<Vruta::complex_promise> h) noexcept;
175};
176
177/**
178 * @struct GetPromiseBase
179 * @brief Templated awaitable for accessing a coroutine's promise object
180 *
181 * This template allows coroutines to access their own promise object in a
182 * type-safe, domain-agnostic way. Each domain (audio, graphics, complex, event)
183 * can instantiate this template with their specific promise type.
184 *
185 * @tparam PromiseType The promise type to access (audio_promise, graphics_promise, etc.)
186 */
187template <typename PromiseType>
188struct MAYAFLUX_API GetPromiseBase {
189 using promise_handle = PromiseType;
190
191 /**
192 * @brief Pointer to store the promise object
193 *
194 * This field is set during await_suspend and returned by
195 * await_resume, providing the coroutine with access to its
196 * own promise object.
197 */
198 promise_handle* promise_ptr = nullptr;
199
200 GetPromiseBase() = default;
201
202 [[nodiscard]] inline bool await_ready() const noexcept
203 {
204 return false;
205 }
206
207 void await_suspend(std::coroutine_handle<promise_handle> h) noexcept
208 {
209 promise_ptr = &h.promise();
210 h.promise().active_delay_context = Vruta::DelayContext::AWAIT;
211 }
212
213 [[nodiscard]] promise_handle& await_resume() const noexcept
214 {
215 return *promise_ptr;
216 }
217};
218
219/**
220 * @brief Audio domain promise accessor
221 *
222 * Usage in SoundRoutine:
223 * ```cpp
224 * auto routine = []() -> SoundRoutine {
225 * auto& promise = co_await GetPromise{};
226 * // or explicitly: co_await GetAudioPromise{};
227 * // promise is audio_promise&
228 * };
229 * ```
230 */
232
233/**
234 * @brief Graphics domain promise accessor
235 *
236 * Usage in GraphicsRoutine:
237 * ```cpp
238 * auto routine = []() -> GraphicsRoutine {
239 * auto& promise = co_await GetGraphicsPromise{};
240 * // promise is graphics_promise&
241 * };
242 * ```
243 */
245
246/**
247 * @brief Multi-domain promise accessor
248 *
249 * Usage in ComplexRoutine:
250 * ```cpp
251 * auto routine = []() -> ComplexRoutine {
252 * auto& promise = co_await GetComplexPromise{};
253 * // promise is complex_promise&
254 * };
255 * ```
256 */
258
259/**
260 * @brief Event-driven promise accessor
261 *
262 * Usage in Event coroutines:
263 * ```cpp
264 * auto routine = []() -> Event {
265 * auto& promise = co_await GetEventPromise{};
266 * // promise is event_promise&
267 * };
268 * ```
269 */
271
272/**
273 * @class EventAwaiter
274 * @brief Awaiter for suspending on window events
275 *
276 * Usage:
277 * auto event = co_await window->get_event_source().next_event();
278 * auto key_event = co_await window->get_event_source().await_event(WindowEventType::KEY_PRESSED);
279 */
280class MAYAFLUX_API EventAwaiter {
281public:
282 EventAwaiter(Vruta::EventSource& source, std::optional<Core::WindowEventType> filter = std::nullopt)
283 : m_source(source)
284 , m_filter(filter)
285 {
286 }
287
289
290 EventAwaiter(const EventAwaiter&) = delete;
292 EventAwaiter(EventAwaiter&&) noexcept = default;
293 EventAwaiter& operator=(EventAwaiter&&) noexcept = delete;
294
295 /**
296 * @brief Check if event already available
297 */
298 bool await_ready();
299
300 /**
301 * @brief Suspend coroutine, register for event notification
302 */
303 void await_suspend(std::coroutine_handle<> handle);
304
305 /**
306 * @brief Resume with event data
307 */
308 Core::WindowEvent await_resume();
309
310 /**
311 * @brief Called by EventSource when event arrives
312 */
313 void try_resume();
314
315private:
316 Vruta::EventSource& m_source;
317 std::optional<Core::WindowEventType> m_filter;
318 Core::WindowEvent m_result;
319 std::coroutine_handle<> m_handle;
320 bool m_is_suspended = false;
321
322 friend class Vruta::EventSource;
323};
324}
EventAwaiter & operator=(const EventAwaiter &)=delete
EventAwaiter(EventAwaiter &&) noexcept=default
EventAwaiter(Vruta::EventSource &source, std::optional< Core::WindowEventType > filter=std::nullopt)
Definition Awaiters.hpp:282
EventAwaiter(const EventAwaiter &)=delete
Awaiter for suspending on window events.
Definition Awaiters.hpp:280
Awaitable event stream for window events.
constexpr void await_resume() const noexcept
Definition Awaiters.hpp:131
void await_suspend(std::coroutine_handle< promise_handle > h) noexcept
Definition Awaiters.hpp:123
BufferDelay(uint64_t cycles)
Definition Awaiters.hpp:114
constexpr bool await_ready() const noexcept
Definition Awaiters.hpp:121
Awaiter for suspending until a buffer cycle boundary.
Definition Awaiters.hpp:105
constexpr bool await_ready() const noexcept
Definition Awaiters.hpp:152
constexpr void await_resume() const noexcept
Definition Awaiters.hpp:157
graphics-domain awaiter for frame-accurate timing delays
Definition Awaiters.hpp:141
promise_handle & await_resume() const noexcept
Definition Awaiters.hpp:213
bool await_ready() const noexcept
Definition Awaiters.hpp:202
void await_suspend(std::coroutine_handle< promise_handle > h) noexcept
Definition Awaiters.hpp:207
Templated awaitable for accessing a coroutine's promise object.
Definition Awaiters.hpp:188
constexpr void await_resume() const noexcept
Definition Awaiters.hpp:172
constexpr bool await_ready() const noexcept
Definition Awaiters.hpp:167
uint64_t samples_to_wait
Number of time units to wait before resuming the coroutine.
Definition Awaiters.hpp:51
void await_resume()
Called when the coroutine is resumed after the delay.
Definition Awaiters.hpp:75
SampleDelay(uint64_t samples)
Definition Awaiters.hpp:53
bool await_ready() const
Checks if the delay should be bypassed.
Definition Awaiters.hpp:66
Awaitable object for precise sample-accurate timing delays.
Definition Awaiters.hpp:35
Coroutine promise type for audio processing tasks with sample-accurate timing.
Definition Promise.hpp:196
Coroutine promise type for graphics processing tasks with frame-accurate timing.
Definition Promise.hpp:259