MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
BroadcastAwaiter.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "EventAwaiter.hpp"
5
6namespace MayaFlux::Kriya {
7
8/**
9 * @class BroadcastAwaiter
10 * @brief Awaiter for suspending a coroutine until a BroadcastSource<T> fires.
11 *
12 * Works with any coroutine type: SoundRoutine, GraphicsRoutine, Event,
13 * ComplexRoutine. The awaiter does not own the source; the source must
14 * outlive any suspended awaiter.
15 *
16 * Edge-triggered: await_ready() returns true only when a value arrived
17 * before this co_await expression (pending slot occupied). Otherwise the
18 * coroutine suspends and is resumed by the next signal() call.
19 *
20 * One BroadcastAwaiter may be registered against a BroadcastSource at a
21 * time. For fan-out to multiple consumers, use one BroadcastSource per
22 * consumer.
23 *
24 * The captured shared_ptr to the BroadcastSource must be copied into a
25 * coroutine-local variable before first use, not referenced only through
26 * the lambda closure. The lambda closure lives on the caller's stack;
27 * the coroutine frame is heap-allocated and outlives the caller.
28 *
29 * @code
30 * auto src = make_persistent_shared<Vruta::BroadcastSource<MyType>>();
31 *
32 * auto routine = [src]() -> Vruta::Event {
33 * auto local_src = src; // pull into coroutine frame
34 * while (true) {
35 * auto val = co_await local_src->next();
36 * }
37 * };
38 * @endcode
39 *
40 * @tparam T Payload type matching the bound BroadcastSource<T>.
41 * @see BroadcastSource
42 */
43template <typename T>
45public:
47 : m_source(source)
48 {
49 }
50
52 {
54 m_source.unregister_waiter(this);
55 }
56
59 BroadcastAwaiter(BroadcastAwaiter&&) noexcept = default;
60 BroadcastAwaiter& operator=(BroadcastAwaiter&&) noexcept = delete;
61
62 /**
63 * @brief Returns true if a pending value is already available.
64 *
65 * Consumes the pending value on success. The coroutine does not suspend.
66 */
68 {
69 auto val = m_source.pop_pending();
70 if (val) {
71 m_result = std::move(*val);
72 return true;
73 }
74 return false;
75 }
76
77 /**
78 * @brief Register with the source and suspend, or consume a pending value
79 * that arrived in the race window and return false (no suspend).
80 *
81 * @param handle Coroutine handle.
82 * @return true if the coroutine should suspend, false if it should continue.
83 */
84 bool await_suspend(std::coroutine_handle<> handle)
85 {
86 m_handle = handle;
87 m_is_suspended = true;
88 m_source.register_waiter(this);
89
90 if (auto val = m_source.pop_pending()) {
91 m_source.unregister_waiter(this);
92 m_result = std::move(*val);
93 m_is_suspended = false;
94 return false;
95 }
96
97 return true;
98 }
99
100 /**
101 * @brief Return the delivered value on resume.
102 */
104 {
105 m_is_suspended = false;
106 return std::move(m_result);
107 }
108
109 /**
110 * @brief Called by BroadcastSource::signal() from any thread.
111 * @param value Value committed by the signaller.
112 */
113 void deliver(const T& value)
114 {
115 m_result = value;
116 m_is_suspended = false;
117 m_handle.resume();
118 }
119
120 /**
121 * @brief Satisfies EventAwaiter interface. BroadcastAwaiter bypasses
122 * the EventSource dispatch() path; deliver() is called directly.
123 */
124 void try_resume(const void*) override { }
125
126 /**
127 * @brief BroadcastAwaiter has no filter semantics. Always returns true.
128 */
129 [[nodiscard]] bool filter_matches(const void*) const override { return true; }
130
131private:
134};
135
136} // namespace MayaFlux::Kriya
bool await_suspend(std::coroutine_handle<> handle)
Register with the source and suspend, or consume a pending value that arrived in the race window and ...
bool await_ready()
Returns true if a pending value is already available.
BroadcastAwaiter(Vruta::BroadcastSource< T > &source)
bool filter_matches(const void *) const override
BroadcastAwaiter has no filter semantics.
T await_resume()
Return the delivered value on resume.
BroadcastAwaiter(const BroadcastAwaiter &)=delete
BroadcastAwaiter(BroadcastAwaiter &&) noexcept=default
void try_resume(const void *) override
Satisfies EventAwaiter interface.
Vruta::BroadcastSource< T > & m_source
BroadcastAwaiter & operator=(const BroadcastAwaiter &)=delete
void deliver(const T &value)
Called by BroadcastSource::signal() from any thread.
Awaiter for suspending a coroutine until a BroadcastSource<T> fires.
std::coroutine_handle m_handle
Abstract base for all event-driven awaiters.
Awaitable single-value broadcast channel for cross-thread signal delivery.