MayaFlux 0.5.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
DataProcessingChain.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "DataProcessor.hpp"
4
5namespace MayaFlux::Kakshya {
6
7/**
8 * @class DataProcessingChain
9 * @brief Manages collections of DataProcessor objects as composable, container-specific pipelines.
10 *
11 * Each SignalSourceContainer maintains its own ordered processor sequence. Processors can be
12 * added, removed, or reordered at runtime. All process variants guard against iterator
13 * invalidation via an atomic processing flag; removal requests that arrive mid-iteration
14 * are deferred and drained after the loop completes.
15 */
16class MAYAFLUX_API DataProcessingChain {
17public:
19
20 /**
21 * @brief Adds a processor to the end of the chain for a specific container.
22 * @param processor The data processor to add.
23 * @param container The signal container the processor will operate on.
24 * @param tag Optional tag for selective execution via process_tagged().
25 */
26 void add_processor(
27 const std::shared_ptr<DataProcessor>& processor,
28 const std::shared_ptr<SignalSourceContainer>& container,
29 const std::string& tag = "");
30
31 /**
32 * @brief Adds a processor at a specific position in the chain.
33 * @param processor The data processor to add.
34 * @param container The signal container the processor will operate on.
35 * @param position Zero-based insertion index; appends if out of range.
36 */
37 void add_processor_at(
38 const std::shared_ptr<DataProcessor>& processor,
39 const std::shared_ptr<SignalSourceContainer>& container,
40 size_t position);
41
42 /**
43 * @brief Removes a processor from a container's chain.
44 * @param processor The data processor to remove.
45 * @param container The signal container to remove the processor from.
46 *
47 * If called while a process variant is iterating, the removal is deferred
48 * until the current iteration completes.
49 */
51 const std::shared_ptr<DataProcessor>& processor,
52 const std::shared_ptr<SignalSourceContainer>& container);
53
54 /**
55 * @brief Processes a container with all its associated processors in sequence.
56 * @param container The signal container to process.
57 */
58 void process(const std::shared_ptr<SignalSourceContainer>& container);
59
60 /**
61 * @brief Processes a container with only the processors matching a filter predicate.
62 * @param container The signal container to process.
63 * @param filter Predicate returning true for processors that should run.
64 */
65 void process_filtered(
66 const std::shared_ptr<SignalSourceContainer>& container,
67 const std::function<bool(const std::shared_ptr<DataProcessor>&)>& filter);
68
69 /**
70 * @brief Processes a container with only the processors carrying a specific tag.
71 * @param container The signal container to process.
72 * @param tag Tag string to match against registered processor tags.
73 */
74 void process_tagged(
75 const std::shared_ptr<SignalSourceContainer>& container,
76 const std::string& tag);
77
78 /**
79 * @brief Processes a container with only processors of a specific derived type.
80 * @tparam ProcessorType Concrete DataProcessor subtype to dispatch to.
81 * @param container The signal container to process.
82 */
83 template <typename ProcessorType>
84 void process_typed(const std::shared_ptr<SignalSourceContainer>& container)
85 {
86 bool expected = false;
87 if (!m_is_processing.compare_exchange_strong(expected, true,
88 std::memory_order_acquire, std::memory_order_relaxed)) {
89 return;
90 }
91
92 auto it = m_container_processors.find(container);
93 if (it != m_container_processors.end()) {
94 for (auto& processor : it->second) {
95 if (auto typed = std::dynamic_pointer_cast<ProcessorType>(processor)) {
96 typed->process(container);
97 }
98 }
99 }
100
101 m_is_processing.store(false, std::memory_order_release);
102 drain_pending_removals();
103 }
104
105private:
106 /**
107 * @brief Performs immediate removal of a processor from the chain.
108 * @param processor The processor to remove.
109 * @param container The container whose chain is modified.
110 */
111 void remove_processor_direct(
112 const std::shared_ptr<DataProcessor>& processor,
113 const std::shared_ptr<SignalSourceContainer>& container);
114
115 /**
116 * @brief Flushes all removals deferred during the most recent process iteration.
117 */
118 void drain_pending_removals();
119
120 /**
121 * @brief Maps each container to its ordered processor sequence.
122 */
123 std::unordered_map<
124 std::shared_ptr<SignalSourceContainer>,
125 std::vector<std::shared_ptr<DataProcessor>>>
127
128 /**
129 * @brief Maps processors to their optional tag strings.
130 */
131 std::unordered_map<std::shared_ptr<DataProcessor>, std::string> m_processor_tags;
132
133 /**
134 * @brief Removals deferred because they arrived during active iteration.
135 *
136 * Each entry is a (processor, container) pair drained by drain_pending_removals()
137 * after the enclosing process variant returns.
138 */
139 std::vector<std::pair<std::shared_ptr<DataProcessor>,
140 std::shared_ptr<SignalSourceContainer>>>
142
143 /**
144 * @brief Guards all process variants against concurrent or re-entrant iteration.
145 *
146 * Set to true at the start of any process variant via CAS; cleared after the
147 * loop and pending-removal drain complete. remove_processor() checks this flag
148 * before deciding whether to act immediately or defer.
149 */
150 std::atomic<bool> m_is_processing { false };
151};
152
153} // namespace MayaFlux::Kakshya
void process_typed(const std::shared_ptr< SignalSourceContainer > &container)
Processes a container with only processors of a specific derived type.
std::unordered_map< std::shared_ptr< SignalSourceContainer >, std::vector< std::shared_ptr< DataProcessor > > > m_container_processors
Maps each container to its ordered processor sequence.
std::vector< std::pair< std::shared_ptr< DataProcessor >, std::shared_ptr< SignalSourceContainer > > > m_pending_removal
Removals deferred because they arrived during active iteration.
std::unordered_map< std::shared_ptr< DataProcessor >, std::string > m_processor_tags
Maps processors to their optional tag strings.
Manages collections of DataProcessor objects as composable, container-specific pipelines.
void remove_processor(const std::shared_ptr< Buffers::BufferProcessor > &processor, const std::shared_ptr< Buffers::Buffer > &buffer)
Removes a processor from a specific buffer.
Definition Graph.cpp:152
void add_processor(const std::shared_ptr< Buffers::BufferProcessor > &processor, const std::shared_ptr< Buffers::Buffer > &buffer, Buffers::ProcessingToken token)
Adds a processor to a specific buffer.
Definition Graph.cpp:137