MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
BackendRegistry.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <typeindex>
4
5namespace MayaFlux::Registry {
6
7/**
8 * @brief Thread-safe singleton registry for backend service discovery
9 *
10 * Provides centralized, type-safe registry for backend capabilities without
11 * creating dependencies between processing components and specific backend
12 * implementations. Backends register their services on initialization, and
13 * processing components (Buffers, Nodes, Coroutines, etc.) query for needed
14 * capabilities at runtime.
15 *
16 * Design Philosophy:
17 * - Zero coupling between consumers and backends
18 * - Runtime service discovery with compile-time type safety
19 * - Graceful degradation when services unavailable
20 * - Thread-safe for concurrent access across subsystems
21 * - Singleton to avoid engine/subsystem dependencies
22 * - Hot-swappable backends via re-registration
23 *
24 * Thread Safety:
25 * All methods are thread-safe. Registration and queries can occur concurrently
26 * from different threads. Uses shared_mutex for optimal read performance
27 * (multiple concurrent queries, exclusive write for registration).
28 *
29 * Lifecycle:
30 * 1. Backend initializes and registers services
31 * 2. Consumers query for services as needed
32 * 3. Backend shuts down and unregisters services
33 * 4. Registry remains valid for next backend initialization
34 *
35 * Example Usage:
36 *
37 * Backend registration:
38 * auto& registry = BackendRegistry::instance();
39 * registry.register_service<IBufferService>([this]() -> void* {
40 * return m_buffer_service.get();
41 * });
42 *
43 * Consumer query:
44 * auto* service = BackendRegistry::instance().get_service<IBufferService>();
45 * if (service) {
46 * service->create_buffer(...);
47 * }
48 */
49class MAYAFLUX_API BackendRegistry {
50public:
51 using ServiceId = std::type_index;
52 using ServiceFactory = std::function<void*()>;
53
54 /**
55 * @brief Get the global registry instance
56 * @return Reference to singleton registry
57 *
58 * Thread-safe initialization via static local variable (C++11 guarantee).
59 * Instance is never destroyed - lives for program duration.
60 */
61 static BackendRegistry& instance();
62
67
68 /**
69 * @brief Register a backend service capability
70 * @tparam Interface The service interface type being provided
71 * @param factory Factory function returning pointer to service implementation
72 *
73 * Thread-safe. Multiple registrations of the same interface type will
74 * overwrite previous registrations, enabling backend hot-swapping.
75 *
76 * The factory is called each time get_service() is invoked, allowing
77 * backends to return context-specific implementations if needed.
78 *
79 * Example:
80 * registry.register_service<IBufferService>([this]() -> void* {
81 * return static_cast<IBufferService*>(&m_buffer_service_impl);
82 * });
83 */
84 template <typename Interface>
86 {
87 std::unique_lock lock(m_mutex);
88 m_services[typeid(Interface)] = std::move(factory);
89 }
90
91 /**
92 * @brief Query for a backend service
93 * @tparam Interface The service interface type needed
94 * @return Pointer to service implementation or nullptr if unavailable
95 *
96 * Thread-safe. Returns nullptr if service not registered - callers
97 * must always check for nullptr before use.
98 *
99 * The returned pointer is valid as long as the backend remains alive.
100 * Do not cache pointers across backend lifetime boundaries.
101 *
102 * Example:
103 * auto* service = registry.get_service<IBufferService>();
104 * if (service) {
105 * auto buffer = service->create_buffer(...);
106 * } else {
107 * // Handle missing service gracefully
108 * }
109 */
110 template <typename Interface>
111 Interface* get_service()
112 {
113 std::shared_lock lock(m_mutex);
114 auto it = m_services.find(typeid(Interface));
115 if (it != m_services.end()) {
116 return static_cast<Interface*>(it->second());
117 }
118 return nullptr;
119 }
120
121 /**
122 * @brief Check if a service is available
123 * @tparam Interface The service interface type to check
124 * @return True if service is currently registered
125 *
126 * Thread-safe. Useful for capability detection without error handling.
127 * Note: Service availability can change between has_service() and
128 * get_service() calls due to concurrent unregistration.
129 *
130 * Example:
131 * if (registry.has_service<IComputeService>()) {
132 * // Compute shaders available
133 * }
134 */
135 template <typename Interface>
136 bool has_service() const
137 {
138 std::shared_lock lock(m_mutex);
139 return m_services.contains(typeid(Interface));
140 }
141
142 /**
143 * @brief Unregister a service
144 * @tparam Interface The service interface type to unregister
145 *
146 * Thread-safe. Typically called during backend shutdown.
147 * Safe to call even if service not registered (no-op).
148 * After unregistration, get_service() will return nullptr.
149 *
150 * Example:
151 * registry.unregister_service<IBufferService>();
152 */
153 template <typename Interface>
155 {
156 std::unique_lock lock(m_mutex);
157 m_services.erase(typeid(Interface));
158 }
159
160 /**
161 * @brief Clear all registered services
162 *
163 * Thread-safe. Useful for testing or complete system reset.
164 * Typically called during engine shutdown to ensure clean state.
165 */
167 {
168 std::unique_lock lock(m_mutex);
169 m_services.clear();
170 }
171
172 /**
173 * @brief Get count of currently registered services
174 * @return Number of registered service types
175 *
176 * Thread-safe. Primarily for debugging and diagnostics.
177 */
178 size_t get_service_count() const
179 {
180 std::shared_lock lock(m_mutex);
181 return m_services.size();
182 }
183
184private:
185 BackendRegistry() = default;
186 ~BackendRegistry() = default;
187
188 mutable std::shared_mutex m_mutex;
189 std::unordered_map<ServiceId, ServiceFactory> m_services;
190};
191
192} // namespace MayaFlux::Registry
vk::Instance instance
Definition VKDevice.cpp:39
Interface * get_service()
Query for a backend service.
void register_service(ServiceFactory factory)
Register a backend service capability.
BackendRegistry(const BackendRegistry &)=delete
BackendRegistry & operator=(const BackendRegistry &)=delete
std::function< void *()> ServiceFactory
std::unordered_map< ServiceId, ServiceFactory > m_services
BackendRegistry(BackendRegistry &&)=delete
size_t get_service_count() const
Get count of currently registered services.
BackendRegistry & operator=(BackendRegistry &&)=delete
bool has_service() const
Check if a service is available.
void clear_all_services()
Clear all registered services.
void unregister_service()
Unregister a service.
Thread-safe singleton registry for backend service discovery.