8 return { std::coroutine_handle<audio_promise>::from_promise(*
this) };
13 return { std::coroutine_handle<graphics_promise>::from_promise(*
this) };
21 "SoundRoutine constructed with invalid coroutine handle");
50 : m_handle(std::exchange(other.m_handle, {}))
57 if (m_handle && m_handle.address())
60 m_handle = std::exchange(other.m_handle, {});
76 return m_handle.promise().processing_token;
93 m_handle.promise().next_sample = current_sample;
94 m_handle.promise().next_buffer_cycle = current_sample;
109 return m_handle.promise().sync_to_clock;
117 auto& promise_ref =
m_handle.promise();
119 if (promise_ref.should_terminate || !promise_ref.auto_resume) {
127 if (promise_ref.active_delay_context !=
DelayContext::NONE && promise_ref.active_delay_context != context) {
131 bool should_resume =
false;
136 should_resume = (current_value >= promise_ref.next_sample);
138 promise_ref.next_sample = current_value + promise_ref.delay_amount;
141 should_resume =
false;
147 should_resume = (current_value >= promise_ref.next_buffer_cycle);
150 promise_ref.next_buffer_cycle = current_value + promise_ref.delay_amount;
153 should_resume =
false;
158 should_resume =
true;
183 set_state<bool>(
"restart",
true);
184 m_handle.promise().auto_resume =
true;
195 m_handle.promise().state[key] = std::move(value);
205 auto& state_map =
m_handle.promise().state;
206 auto it = state_map.find(key);
207 if (it != state_map.end()) {
218 "GraphicsRoutine constructed with invalid coroutine handle");
223 : m_handle(other.m_handle)
229 if (
this != &other) {
236 : m_handle(std::exchange(other.m_handle,
nullptr))
242 if (
this != &other) {
243 m_handle = std::exchange(other.m_handle,
nullptr);
271 m_handle.promise().next_frame = current_frame;
286 return m_handle.promise().sync_to_clock;
294 auto& promise_ref =
m_handle.promise();
296 if (promise_ref.should_terminate || !promise_ref.auto_resume) {
304 if (promise_ref.active_delay_context !=
DelayContext::NONE && promise_ref.active_delay_context != context) {
308 bool should_resume =
false;
313 should_resume = (current_value >= promise_ref.next_frame);
315 promise_ref.next_frame = current_value + promise_ref.delay_amount;
318 should_resume =
false;
323 should_resume =
true;
350 set_state<bool>(
"restart",
true);
351 m_handle.promise().auto_resume =
true;
362 m_handle.promise().state[key] = std::move(value);
372 auto& state_map =
m_handle.promise().state;
373 auto it = state_map.find(key);
374 if (it != state_map.end()) {
void * get_state_impl_raw(const std::string &key) override
bool initialize_state(uint64_t current_frame=0U) override
Initializes the coroutine's state for execution.
void set_state_impl(const std::string &key, std::any value) override
bool try_resume_with_context(uint64_t current_value, DelayContext context) override
Attempts to resume the coroutine with explicit temporal context.
bool is_active() const override
Checks if the coroutine is still active.
~GraphicsRoutine() override
bool requires_clock_sync() const override
Check if the routine should synchronize with a clock.
GraphicsRoutine & operator=(const GraphicsRoutine &other)
Copy assignment operator.
bool restart() override
Restarts the coroutine from the beginning.
uint64_t next_execution() const override
Gets the sample position when this routine should next execute.
std::coroutine_handle< promise_type > m_handle
Handle to the underlying coroutine.
bool try_resume(uint64_t current_context) override
Attempts to resume the coroutine if it's ready to execute.
ProcessingToken get_processing_token() const override
Get the processing token that determines how this routine should be scheduled.
GraphicsRoutine(std::coroutine_handle< promise_type > h)
Constructs a GraphicsRoutine from a coroutine handle.
A C++20 coroutine-based graphics processing task with frame-accurate timing.
std::coroutine_handle< promise_type > m_handle
Handle to the underlying coroutine.
bool is_active() const override
Checks if the coroutine is still active.
bool try_resume_with_context(uint64_t current_value, DelayContext context) override
Attempts to resume the coroutine with explicit temporal context.
void * get_state_impl_raw(const std::string &key) override
uint64_t next_execution() const override
Gets the sample position when this routine should next execute.
void set_state_impl(const std::string &key, std::any value) override
bool requires_clock_sync() const override
Check if the routine should synchronize with a clock.
bool try_resume(uint64_t current_context) override
Attempts to resume the coroutine if it's ready to execute.
SoundRoutine(std::coroutine_handle< promise_type > h)
Constructs a SoundRoutine from a coroutine handle.
SoundRoutine & operator=(const SoundRoutine &other)
Copy assignment operator.
bool restart() override
Restarts the coroutine from the beginning.
ProcessingToken get_processing_token() const override
Get the processing token that determines how this routine should be scheduled.
bool initialize_state(uint64_t current_sample=0U) override
Initializes the coroutine's state for execution.
A C++20 coroutine-based audio processing task with sample-accurate timing.
@ CoroutineScheduling
Coroutine scheduling and temporal coordination (Vruta::TaskScheduler)
@ Vruta
Coroutines, schedulers, clocks, task management.
@ FRAME_ACCURATE
Coroutine is frame-accurate.
@ ON_DEMAND
Coroutine is executed on demand, not scheduled.
DelayContext
Discriminator for different temporal delay mechanisms.
@ FRAME_BASED
Frame-rate delay (Graphics domain)
@ NONE
No active delay, resume immediately.
@ SAMPLE_BASED
Sample-accurate delay (audio domain)
@ BUFFER_BASED
Buffer-cycle delay (audio hardware boundary)
@ AWAIT
Awaiter-induced delay (temporary suspension)
SoundRoutine get_return_object()
Creates the SoundRoutine object returned to the caller.
GraphicsRoutine get_return_object()
Creates the GraphicsRoutine object returned to the caller.