MayaFlux 0.1.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
ComputeRegistry.hpp
Go to the documentation of this file.
1#pragma once
2
4
5namespace MayaFlux::Yantra {
6
7/**
8 * @brief Macro to declare operation traits for automatic registration
9 *
10 * This macro should be used in operation classes to provide intrinsic
11 * type information that the registry can use for automatic categorization.
12 *
13 * Usage:
14 * class MyAnalyzer : public UniversalAnalyzer<...> {
15 * public:
16 * DECLARE_OPERATION_TRAITS(ANALYZER)
17 * // ... rest of implementation
18 * };
19 */
20#define DECLARE_OPERATION_TRAITS(CATEGORY) \
21 static constexpr OperationType operation_category = OperationType::CATEGORY; \
22 using base_input_type = typename base_type::input_type; \
23 using base_output_type = typename base_type::output_type; \
24 static constexpr const char* operation_name = #CATEGORY;
25
26/**
27 * @class OperationRegistry
28 * @brief Manages operation type registration, discovery, and factory creation
29 *
30 * The OperationRegistry acts as a centralized repository for all operation types
31 * in the Yantra compute system. It provides:
32 * - Type-safe registration with automatic trait detection
33 * - Factory-based operation creation
34 * - Discovery mechanisms for finding compatible operations
35 * - Integration points with the broader API/Proxy/Creator system
36 *
37 * This registry follows a similar pattern to the channel/domain/shared_ptr model
38 * but focuses on operation types rather than runtime instances.
39 */
41public:
42 using Factory = std::function<std::any()>;
43
44 /**
45 * @brief Register an operation using its intrinsic traits
46 * @tparam OpClass Operation class with DECLARE_OPERATION_TRAITS
47 */
48 template <typename OpClass>
50 {
52 "Operation must have intrinsic type information. Use DECLARE_OPERATION_TRAITS macro.");
53
54 OperationType category = OpClass::operation_category;
55 register_operation<OpClass>(category);
56 }
57
58 /**
59 * @brief Register with explicit category (for operations without traits)
60 * @tparam OpClass Operation class to register
61 * @param category Explicit operation category
62 */
63 template <typename OpClass>
65 {
66 TypeKey key {
67 .category = category,
68 .operation_type = std::type_index(typeid(OpClass))
69 };
70
71 m_factories[key] = []() -> std::any {
72 return static_pointer_cast<void>(std::make_shared<OpClass>());
73 };
74
75 m_type_info[key] = {
76 std::type_index(typeid(typename OpClass::input_type)),
77 std::type_index(typeid(typename OpClass::output_type))
78 };
79 }
80
81 /**
82 * @brief Register with custom factory function
83 * @tparam OpClass Operation class to register
84 * @param category Operation category
85 * @param factory Custom factory function
86 */
87 template <typename OpClass>
89 std::function<std::shared_ptr<OpClass>()> factory)
90 {
91 TypeKey key {
92 .category = category,
93 .operation_type = std::type_index(typeid(OpClass))
94 };
95
96 m_factories[key] = [factory]() -> std::any {
97 return std::static_pointer_cast<void>(factory());
98 };
99
100 m_type_info[key] = {
101 std::type_index(typeid(typename OpClass::input_type)),
102 std::type_index(typeid(typename OpClass::output_type))
103 };
104 }
105
106 /**
107 * @brief Create an operation instance
108 * @tparam OpClass Operation class to create
109 * @return Shared pointer to new operation instance, or nullptr if not registered
110 */
111 template <typename OpClass>
112 std::shared_ptr<OpClass> create()
113 {
115 TypeKey key { OpClass::operation_category, std::type_index(typeid(OpClass)) };
116 auto it = m_factories.find(key);
117 if (it != m_factories.end()) {
118 return std::static_pointer_cast<OpClass>(
119 std::any_cast<std::shared_ptr<void>>(it->second()));
120 }
121 }
122
123 for (const auto& [key, factory] : m_factories) {
124 if (key.operation_type == std::type_index(typeid(OpClass))) {
125 return std::static_pointer_cast<OpClass>(
126 std::any_cast<std::shared_ptr<void>>(factory()));
127 }
128 }
129
130 return nullptr;
131 }
132
133 /**
134 * @brief Check if an operation type is registered
135 * @tparam OpClass Operation class to check
136 * @return true if registered, false otherwise
137 */
138 template <typename OpClass>
139 bool is_registered() const
140 {
141 return std::ranges::any_of(m_factories, [](const auto& pair) {
142 const auto& key = pair.first;
143 return key.operation_type == std::type_index(typeid(OpClass));
144 });
145 }
146
147 /**
148 * @brief Discover operations matching specific criteria
149 * @param category Operation category to search
150 * @param input_type Required input type
151 * @param output_type Required output type
152 * @return Vector of type indices for matching operations
153 */
154 std::vector<std::type_index> discover_operations(OperationType category,
155 std::type_index input_type,
156 std::type_index output_type) const
157 {
158 std::vector<std::type_index> results;
159
160 for (const auto& [key, type_info] : m_type_info) {
161 if (key.category == category && type_info.first == input_type && type_info.second == output_type) {
162 results.push_back(key.operation_type);
163 }
164 }
165
166 return results;
167 }
168
169 /**
170 * @brief Get all registered operations of a specific category
171 * @param category Category to query
172 * @return Vector of type indices for operations in that category
173 */
174 std::vector<std::type_index> get_operations_by_category(OperationType category) const
175 {
176 std::vector<std::type_index> results;
177
178 for (const auto& [key, _] : m_factories) {
179 if (key.category == category) {
180 results.push_back(key.operation_type);
181 }
182 }
183
184 return results;
185 }
186
187 /**
188 * @brief Get category for a registered operation type
189 * @tparam OpClass Operation class to query
190 * @return Optional containing the category if registered
191 */
192 template <typename OpClass>
193 std::optional<OperationType> get_category() const
194 {
195 auto type_idx = std::type_index(typeid(OpClass));
196
197 for (const auto& [key, _] : m_factories) {
198 if (key.operation_type == type_idx) {
199 return key.category;
200 }
201 }
202
203 return std::nullopt;
204 }
205
206 /**
207 * @brief Clear all registrations
208 */
209 void clear()
210 {
211 m_factories.clear();
212 m_type_info.clear();
213 }
214
215 /**
216 * @brief Get total number of registered operations
217 */
218 size_t size() const
219 {
220 return m_factories.size();
221 }
222
223private:
224 struct TypeKey {
226 std::type_index operation_type;
227
228 bool operator==(const TypeKey& other) const
229 {
230 return category == other.category && operation_type == other.operation_type;
231 }
232 };
233
234 struct TypeKeyHash {
235 std::size_t operator()(const TypeKey& key) const
236 {
237 return std::hash<int>()(static_cast<int>(key.category)) ^ std::hash<std::type_index>()(key.operation_type);
238 }
239 };
240
241 std::unordered_map<TypeKey, Factory, TypeKeyHash> m_factories;
242 std::unordered_map<TypeKey, std::pair<std::type_index, std::type_index>, TypeKeyHash> m_type_info;
243
244 template <typename T, typename = void>
245 struct has_operation_category : std::false_type { };
246
247 template <typename T>
248 struct has_operation_category<T, std::void_t<decltype(T::operation_category)>>
249 : std::true_type { };
250
251 template <typename T, typename = void>
252 struct has_operation_traits : std::false_type { };
253
254 template <typename T>
255 struct has_operation_traits<T, std::void_t<decltype(T::operation_category), typename T::input_type, typename T::output_type>> : std::true_type { };
256};
257
258/**
259 * @brief Global operation registry accessor
260 * Similar to how Engine provides global access to core systems
261 */
262inline std::shared_ptr<OperationRegistry> get_operation_registry()
263{
264 static auto registry = std::make_shared<OperationRegistry>();
265 return registry;
266}
267
268/**
269 * @brief Automatic registration helper
270 * Operations can use this in their implementation files for auto-registration
271 */
272template <typename OpClass>
275 {
276 get_operation_registry()->register_operation<OpClass>();
277 }
278};
279
280/**
281 * @brief Macro for automatic registration in implementation files
282 * Usage: REGISTER_OPERATION(MyAnalyzer);
283 */
284#define REGISTER_OPERATION(OpClass) \
285 static MayaFlux::Yantra::AutoRegisterOperation<OpClass> _auto_register_##OpClass;
286
287} // namespace MayaFlux::Yantra
size_t size() const
Get total number of registered operations.
void register_operation(OperationType category)
Register with explicit category (for operations without traits)
bool is_registered() const
Check if an operation type is registered.
std::unordered_map< TypeKey, Factory, TypeKeyHash > m_factories
void register_operation()
Register an operation using its intrinsic traits.
std::unordered_map< TypeKey, std::pair< std::type_index, std::type_index >, TypeKeyHash > m_type_info
void register_operation_with_factory(OperationType category, std::function< std::shared_ptr< OpClass >()> factory)
Register with custom factory function.
std::vector< std::type_index > get_operations_by_category(OperationType category) const
Get all registered operations of a specific category.
std::function< std::any()> Factory
std::vector< std::type_index > discover_operations(OperationType category, std::type_index input_type, std::type_index output_type) const
Discover operations matching specific criteria.
std::shared_ptr< OpClass > create()
Create an operation instance.
void clear()
Clear all registrations.
std::optional< OperationType > get_category() const
Get category for a registered operation type.
Manages operation type registration, discovery, and factory creation.
OperationType
Operation categories for organization and discovery.
std::shared_ptr< OperationRegistry > get_operation_registry()
Global operation registry accessor Similar to how Engine provides global access to core systems.
Automatic registration helper Operations can use this in their implementation files for auto-registra...
std::size_t operator()(const TypeKey &key) const
bool operator==(const TypeKey &other) const