MayaFlux 0.2.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
RootNode.hpp
Go to the documentation of this file.
1#pragma once
2
4
5#define MAX_PENDING_NODES 2048
6
7namespace MayaFlux::Nodes {
8
9class Node;
10
11/**
12 * @class RootNode
13 * @brief Container for top-level nodes in a processing channel with multi-modal support
14 *
15 * The RootNode serves as a collection point for multiple independent nodes
16 * that contribute to a single channel's output. Unlike regular nodes,
17 * a RootNode doesn't process data itself but rather manages and combines
18 * the outputs of its registered nodes.
19 *
20 * With multi-modal support, the RootNode can handle different processing rates
21 * (e.g., audio rate, visual rate, custom rates) in a single channel. This enables
22 * advanced scenarios where nodes with different processing requirements coexist.
23 *
24 * Each processing channel has its own RootNode, which collects and
25 * processes all nodes that should output to that channel. The RootNode
26 * processes all registered nodes and aggregates their outputs based on their
27 * assigned processing rates.
28 */
29class MAYAFLUX_API RootNode {
30public:
31 /**
32 * @brief Constructs a RootNode for a specific processing token and channel
33 * @param token The processing domain (e.g., AUDIO_RATE)
34 * @param channel The channel index (default: 0)
35 *
36 * Initializes the root node for the given processing domain and channel.
37 * Each channel and processing domain combination should have its own RootNode.
38 */
39 RootNode(ProcessingToken token = ProcessingToken::AUDIO_RATE, uint32_t channel = 0);
40
41 /**
42 * @brief Adds a node to this root node
43 * @param node The node to register
44 *
45 * Registered nodes will be processed when the root node's process()
46 * method is called, and their outputs will be combined together.
47 * If called during processing, the operation is deferred until safe.
48 */
49 void register_node(const std::shared_ptr<Node>& node);
50
51 /**
52 * @brief Removes a node from this root node
53 * @param node The node to unregister
54 *
55 * After unregistering, the node will no longer contribute to
56 * the root node's output. If called during processing, the operation
57 * is deferred until safe.
58 */
59 void unregister_node(const std::shared_ptr<Node>& node);
60
61 /** @brief Checks if the root node can process pending operations
62 * @return True if successful
63 *
64 * This method can be used to determine if the root node is in the middle
65 * of a processing cycle. If true, queued pending operations will be executed
66 */
67 bool preprocess();
68
69 /** @brief Performs post-processing after all nodes have been processed
70 *
71 * This method unregisters channel usage on the node, cleans up state
72 * and resets processing flags.
73 */
74 void postprocess();
75
76 /**
77 * @brief Processes a single sample from all registered nodes
78 * @return Combined output sample from all nodes
79 *
80 * This method processes each registered node and combines their outputs
81 * into a single sample. It is typically called in a loop to process
82 * multiple samples, but can also be used for single-sample processing.
83 */
84 double process_sample();
85
86 /**
87 * @brief Processes a single frame from all registered nodes
88 *
89 * This method processes each registered node for a single frame.
90 * It is useful in scenarios where frame-based processing is required,
91 * such as visual or animation data processing.
92 */
93 void process_frame();
94
95 /**
96 * @brief Processes all registered nodes and combines their outputs
97 * @param num_samples Number of samples to process
98 * @return Vector containing the combined output samples
99 *
100 * This method calls process_batch() on each registered node and
101 * aggregates their outputs together. The result is the combined output
102 * of all nodes registered with this root node.
103 * If nodes are added or removed during processing, those operations are
104 * deferred until after processing completes.
105 */
106 std::vector<double> process_batch(uint32_t num_samples);
107
108 /**
109 * @brief Processes multiple frames from all registered nodes
110 * @param num_frames Number of frames to process
111 *
112 * This method calls process_batch_frame() on each registered node
113 * for the specified number of frames. It is useful for scenarios
114 * requiring batch frame processing.
115 */
116 void process_batch_frame(uint32_t num_frames);
117
118 /**
119 * @brief Gets the number of nodes registered with this root node
120 * @return Number of registered nodes
121 */
122 inline unsigned int get_node_size() { return m_Nodes.size(); }
123
124 /**
125 * @brief Removes all nodes from this root node
126 *
127 * After calling this method, the root node will have no registered
128 * nodes and will output zero values.
129 */
130 inline void clear_all_nodes() { m_Nodes.clear(); }
131
132 /**
133 * @brief Gets the channel index associated with this root node
134 * @return The channel index
135 */
136 inline uint32_t get_channel() { return m_channel; }
137
138 /**
139 * @brief Gets the processing token associated with this root node
140 * @return The processing token (domain)
141 */
142 inline ProcessingToken get_token() { return m_token; }
143
144 /**
145 * @brief Terminates all nodes registered with this root node
146 *
147 * This method unregisters all node processing and stops
148 * active processing contexts but does not clear nodes
149 */
150 void terminate_all_nodes();
151
152private:
153 /**
154 * @brief Collection of nodes registered with this root node
155 *
156 * All nodes in this collection will be processed when the root
157 * node's process() method is called.
158 */
159 std::vector<std::shared_ptr<Node>> m_Nodes;
160
161 /**
162 * @brief Flag indicating if the root node is currently processing nodes
163 *
164 * This atomic flag prevents concurrent modifications to the node collection
165 * during processing cycles. When set to true, any attempts to register or
166 * unregister nodes will be queued as pending operations rather than being
167 * executed immediately, ensuring thread safety and preventing data corruption
168 * during audio processing.
169 */
170 std::atomic<bool> m_is_processing;
171
172 /**
173 * @brief Flag to request termination of processing
174 *
175 * When set to true, this flag indicates that all processing
176 * should be terminated cleanly.
177 */
178 std::atomic<bool> m_request_terminate { false };
179
180 /**
181 * @brief Structure for storing pending node registration/unregistration operations
182 *
183 * When nodes need to be added or removed while the root node is processing,
184 * these operations are stored in this structure and executed later when it's
185 * safe to modify the node collection. This prevents race conditions and ensures
186 * consistent audio processing without interruptions.
187 */
188 struct PendingOp {
189 /**
190 * @brief Flag indicating if this pending operation slot is in use
191 */
192 std::atomic<bool> active;
193
194 /**
195 * @brief The node to be registered or unregistered
196 */
197 std::shared_ptr<Node> node;
198 } m_pending_ops[MAX_PENDING_NODES];
199
200 /**
201 * @brief Counter tracking the number of pending operations
202 *
203 * This counter helps efficiently manage the pending operations array,
204 * allowing the system to quickly determine if there are operations
205 * waiting to be processed without scanning the entire array.
206 */
207 std::atomic<uint32_t> m_pending_count;
208
209 /**
210 * @brief Processes any pending node registration/unregistration operations
211 *
212 * This method is called after the processing cycle completes to handle any
213 * node registration or unregistration requests that came in during processing.
214 * It ensures that node collection modifications happen safely between
215 * processing cycles, maintaining audio continuity while allowing dynamic
216 * changes to the node graph.
217 */
218 void process_pending_operations();
219
220 /**
221 * @brief The processing channel index for this root node
222 *
223 * Each root node is associated with a specific processing channel,
224 * allowing multiple channels to coexist with their own independent
225 * node collections and processing logic.
226 */
227 uint32_t m_channel;
228
229 /**
230 * @brief Flag indicating whether to skip preprocessing and post processing
231 *
232 * This flag can be set to true to skip the pre and post processing steps,
233 * which is useful in scenarios where the root node is not expected
234 * to sync processing state with other channels or is used outside of the
235 * Engine context.
236 */
238
239 /**
240 * @brief The processing token indicating the domain of this root node
241 *
242 * This token specifies the type of processing this root node is responsible for,
243 * such as audio rate, visual rate, or custom processing rates.
244 */
246};
247
248}
#define MAX_PENDING_NODES
Definition RootNode.hpp:5
static MayaFlux::Nodes::ProcessingToken token
Definition Timers.cpp:8
std::vector< std::shared_ptr< Node > > m_Nodes
Collection of nodes registered with this root node.
Definition RootNode.hpp:159
uint32_t m_channel
The processing channel index for this root node.
Definition RootNode.hpp:227
uint32_t get_channel()
Gets the channel index associated with this root node.
Definition RootNode.hpp:136
void clear_all_nodes()
Removes all nodes from this root node.
Definition RootNode.hpp:130
std::atomic< bool > m_is_processing
Flag indicating if the root node is currently processing nodes.
Definition RootNode.hpp:170
bool m_skip_state_management
Flag indicating whether to skip preprocessing and post processing.
Definition RootNode.hpp:237
std::atomic< uint32_t > m_pending_count
Counter tracking the number of pending operations.
Definition RootNode.hpp:207
unsigned int get_node_size()
Gets the number of nodes registered with this root node.
Definition RootNode.hpp:122
ProcessingToken m_token
The processing token indicating the domain of this root node.
Definition RootNode.hpp:245
ProcessingToken get_token()
Gets the processing token associated with this root node.
Definition RootNode.hpp:142
Container for top-level nodes in a processing channel with multi-modal support.
Definition RootNode.hpp:29
ProcessingToken
Enumerates the different processing domains for nodes.
Contains the node-based computational processing system components.
Definition Chronie.hpp:5
void register_node(const std::shared_ptr< Nodes::Node > &node, const Nodes::ProcessingToken &token, uint32_t channel)
Definition Graph.cpp:102
void unregister_node(const std::shared_ptr< Nodes::Node > &node, const Nodes::ProcessingToken &token, uint32_t channel)
Removes a node from the root node of specified channels.
Definition Graph.cpp:81
std::shared_ptr< Node > node
The node to be registered or unregistered.
Definition RootNode.hpp:197
std::atomic< bool > active
Flag indicating if this pending operation slot is in use.
Definition RootNode.hpp:192
Structure for storing pending node registration/unregistration operations.
Definition RootNode.hpp:188