MayaFlux 0.1.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Chain.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "MayaFlux/Utils.hpp"
4#include "Operators.hpp"
5
6namespace MayaFlux::Kriya {
7
8/**
9 * @class EventChain
10 * @brief A sequential chain of timed events with precise temporal control
11 *
12 * The EventChain class provides a way to schedule a sequence of events to occur
13 * at specific time intervals. It's designed for creating temporal sequences of
14 * actions with sample-accurate timing, which is essential for deterministic computational flows.
15 *
16 * This approach is inspired by reactive programming and temporal logic systems
17 * where precise sequencing of operations is critical. It allows for creating complex
18 * temporal behaviors with a simple, declarative API.
19 *
20 * Example usage:
21 * ```cpp
22 * // Create an event chain
23 * EventChain chain(*scheduler);
24 *
25 * // Add events with specific delays
26 * chain.then([]() { process_initial_state(); }) // Immediate
27 * .then([]() { transform_data(); }, 0.5) // After 0.5 seconds
28 * .then([]() { apply_filter(); }, 0.25) // After another 0.25 seconds
29 * .then([]() { finalize_output(); }, 0.25); // After another 0.25 seconds
30 *
31 * // Start the chain
32 * chain.start();
33 * ```
34 *
35 * The EventChain is particularly useful for creating precisely timed computational sequences,
36 * state transitions, or any series of time-based events that need to occur in a specific
37 * order with deterministic timing.
38 */
39class MAYAFLUX_API EventChain {
40public:
41 /**
42 * @brief Constructs an EventChain using the global scheduler
43 *
44 * Creates a new EventChain that will use the global scheduler for timing
45 * operations. This is convenient for simple cases where only one processing
46 * engine is active.
47 */
48 EventChain();
49
50 /**
51 * @brief Constructs an EventChain with an explicit scheduler
52 * @param scheduler The TaskScheduler to use for timing
53 *
54 * Creates a new EventChain that will use the provided scheduler for timing
55 * operations. This allows for more control over which scheduler is used,
56 * which is useful in contexts where multiple processing engines might exist.
57 */
59
60 /**
61 * @brief Adds an event to the chain with a specified delay
62 * @param action Function to execute when the event occurs
63 * @param delay_seconds Time to wait before executing this event (in seconds)
64 * @return Reference to this EventChain for method chaining
65 *
66 * This method adds an event to the chain, to be executed after the specified
67 * delay from the previous event. The first event's delay is measured from
68 * when start() is called.
69 *
70 * The method returns a reference to the EventChain itself, allowing for a
71 * fluent, declarative API style.
72 */
73 EventChain& then(std::function<void()> action, double delay_seconds = 0.F);
74
75 /**
76 * @brief Starts executing the event chain
77 *
78 * This method begins the execution of the event chain, scheduling each event
79 * to occur at its specified time. The events are executed in the order they
80 * were added, with the specified delays between them.
81 *
82 * The timing is sample-accurate, ensuring that each event occurs at precisely
83 * the right moment in the computational timeline.
84 */
85 void start();
86
87private:
88 /**
89 * @brief Structure representing a timed event in the chain
90 *
91 * This structure encapsulates an action to perform and the delay before
92 * performing it, relative to the previous event in the chain.
93 */
94 struct TimedEvent {
95 std::function<void()> action; ///< Function to execute
96 double delay_seconds; ///< Delay before execution
97 };
98
99 /**
100 * @brief Collection of events in this chain
101 *
102 * This vector contains all the events that have been added to the chain,
103 * in the order they will be executed.
104 */
105 std::vector<TimedEvent> m_events;
106
107 /**
108 * @brief Reference to the scheduler that manages timing
109 *
110 * The scheduler provides the timing infrastructure needed for
111 * precise execution of events in the chain.
112 */
114
115 /**
116 * @brief The underlying computational routine that implements the chain
117 *
118 * This coroutine handles the actual timing and execution of events
119 * in the chain. It's created when start() is called.
120 */
121 std::shared_ptr<Vruta::SoundRoutine> m_routine;
122};
123
124/**
125 * @class ActionToken
126 * @brief A token representing an action in a computational sequence
127 *
128 * The ActionToken class represents a single action in a sequence, which can be
129 * a node connection, a time delay, or a function call. It's designed to be used
130 * with the Sequence class to create expressive sequences of computational operations.
131 *
132 * This approach is inspired by dataflow programming and reactive systems,
133 * which use similar concepts to represent sequences of computational events. It allows for
134 * a more intuitive, declarative way of expressing sequences compared to traditional
135 * imperative programming.
136 *
137 * ActionTokens are typically created implicitly through conversions from nodes,
138 * time values, or functions, making the API more concise and expressive.
139 */
140class MAYAFLUX_API ActionToken {
141public:
142 /**
143 * @brief Constructs an ActionToken representing a node connection
144 * @param _node The processing node to connect
145 *
146 * Creates a token that represents connecting a processing node to the output
147 * or applying some other operation to it.
148 */
149 ActionToken(std::shared_ptr<Nodes::Node> _node);
150
151 /**
152 * @brief Constructs an ActionToken representing a time delay
153 * @param _seconds The delay duration in seconds
154 *
155 * Creates a token that represents waiting for a specified amount of time
156 * before proceeding to the next action in the sequence.
157 */
158 ActionToken(double _seconds);
159
160 /**
161 * @brief Constructs an ActionToken representing a function call
162 * @param _func The function to call
163 *
164 * Creates a token that represents calling a function as part of the sequence.
165 * This is useful for triggering state changes or control logic.
166 */
167 ActionToken(std::function<void()> _func);
168
169 /**
170 * @brief The type of action this token represents
171 *
172 * This field indicates whether the token represents a node connection,
173 * a time delay, or a function call.
174 */
176
177 /**
178 * @brief The processing node to connect (for NODE type tokens)
179 *
180 * This field contains the processing node to connect, if this token
181 * represents a node connection.
182 */
183 std::shared_ptr<Nodes::Node> node;
184
185 /**
186 * @brief The function to call (for FUNCTION type tokens)
187 *
188 * This field contains the function to call, if this token
189 * represents a function call.
190 */
191 std::function<void()> func;
192
193 /**
194 * @brief The delay duration in seconds (for TIME type tokens)
195 *
196 * This field contains the delay duration, if this token
197 * represents a time delay.
198 */
199 double seconds = 0.F;
200};
201
202/**
203 * @class Sequence
204 * @brief A sequence of computational operations with a fluent, declarative API
205 *
206 * The Sequence class provides a way to create sequences of computational operations
207 * using a fluent, declarative API with the stream operator (>>). It's designed
208 * for creating expressive sequences of node connections, time delays, and
209 * function calls.
210 *
211 * This approach is inspired by dataflow programming and reactive systems, which
212 * use similar operators to express both data flow and temporal sequencing.
213 * It allows for a more intuitive, declarative way of expressing sequences compared
214 * to traditional imperative programming.
215 *
216 * Example usage:
217 * ```cpp
218 * // Create a sequence
219 * Sequence seq;
220 *
221 * // Define a sequence of operations
222 * seq >> data_source >> 0.5 >> []() { std::cout << "Half second passed" << std::endl; }
223 * >> transform_node >> 0.5 >> output_node;
224 *
225 * // Execute the sequence
226 * seq.execute();
227 * ```
228 *
229 * This creates a sequence that:
230 * 1. Connects data_source to the output
231 * 2. Waits 0.5 seconds
232 * 3. Prints a message
233 * 4. Connects transform_node to the output
234 * 5. Waits 0.5 seconds
235 * 6. Connects output_node to the output
236 *
237 * The Sequence is part of a broader pattern of using operator overloading
238 * to create a domain-specific language for computational flow programming within C++.
239 */
240class MAYAFLUX_API Sequence {
241public:
242 /**
243 * @brief Adds an action to the sequence
244 * @param token The action to add
245 * @return Reference to this Sequence for method chaining
246 *
247 * This operator overload implements the seq >> action syntax, which adds
248 * an action to the sequence. The action can be a node connection, a time
249 * delay, or a function call, represented by an ActionToken.
250 *
251 * The method returns a reference to the Sequence itself, allowing for a
252 * fluent, declarative API style.
253 */
255
256 /**
257 * @brief Executes the sequence using the global managers
258 *
259 * This method executes the sequence of actions using the global node manager
260 * and scheduler. It's convenient for simple cases where only one processing
261 * engine is active.
262 *
263 * The actions are executed in the order they were added, with any time
264 * delays respected.
265 */
266 void execute();
267
268 /**
269 * @brief Executes the sequence with explicit managers
270 * @param node_manager The NodeGraphManager to use for node connections
271 * @param scheduler The TaskScheduler to use for timing
272 *
273 * This method executes the sequence of actions using the provided node manager
274 * and scheduler. This allows for more control over which managers are used,
275 * which is useful in contexts where multiple processing engines might exist.
276 *
277 * The actions are executed in the order they were added, with any time
278 * delays respected.
279 */
280 void execute(const std::shared_ptr<Nodes::NodeGraphManager>& node_manager, const std::shared_ptr<Vruta::TaskScheduler>& scheduler);
281
282private:
283 /**
284 * @brief Collection of actions in this sequence
285 *
286 * This vector contains all the actions that have been added to the sequence,
287 * in the order they will be executed.
288 */
289 std::vector<ActionToken> tokens;
290};
291
292}
static MayaFlux::Nodes::ProcessingToken token
Definition Timers.cpp:8
std::shared_ptr< Nodes::Node > node
The processing node to connect (for NODE type tokens)
Definition Chain.hpp:183
Utils::ActionType type
The type of action this token represents.
Definition Chain.hpp:175
std::function< void()> func
The function to call (for FUNCTION type tokens)
Definition Chain.hpp:191
A token representing an action in a computational sequence.
Definition Chain.hpp:140
Vruta::TaskScheduler & m_Scheduler
Reference to the scheduler that manages timing.
Definition Chain.hpp:113
std::vector< TimedEvent > m_events
Collection of events in this chain.
Definition Chain.hpp:105
std::shared_ptr< Vruta::SoundRoutine > m_routine
The underlying computational routine that implements the chain.
Definition Chain.hpp:121
A sequential chain of timed events with precise temporal control.
Definition Chain.hpp:39
std::vector< ActionToken > tokens
Collection of actions in this sequence.
Definition Chain.hpp:289
A sequence of computational operations with a fluent, declarative API.
Definition Chain.hpp:240
Token-based multimodal task scheduling system for unified coroutine processing.
Definition Scheduler.hpp:51
std::shared_ptr< BufferPipeline > operator>>(std::shared_ptr< BufferPipeline > pipeline, BufferOperation &&operation)
double delay_seconds
Delay before execution.
Definition Chain.hpp:96
std::function< void()> action
Function to execute.
Definition Chain.hpp:95
Structure representing a timed event in the chain.
Definition Chain.hpp:94