CommRaT 2.0.0
C++20 Real-Time Messaging Framework
Loading...
Searching...
No Matches
registry_module.hpp
Go to the documentation of this file.
1#pragma once
2
3// Mailbox infrastructure
7
8// System messaging and platform
13
14// Module aggregator headers (reduce visual clutter)
15#include "commrat/module/module_core.hpp" // I/O specs, traits, config
16#include "commrat/module/module_mixins.hpp" // CRTP mixins (lifecycle, loops, I/O)
17#include "commrat/module/module_services.hpp" // Subscription, publishing, MailboxSet
18
19// External dependencies
20#include <sertial/sertial.hpp>
21#include <atomic>
22#include <vector>
23#include <functional>
24#include <optional>
25
26namespace commrat {
27
28// Empty base classes for conditional multi-input mixin inheritance
29struct EmptyBase2 {}; // MultiInputInfrastructure conditional base
30struct EmptyBase3 {}; // MultiInputProcessor conditional base
31
32// Type trait: Check if a type is std::tuple
33template<typename T>
34struct is_tuple : std::false_type {};
35
36template<typename... Ts>
37struct is_tuple<std::tuple<Ts...>> : std::true_type {};
38
39template<typename T>
40inline constexpr bool is_tuple_v = is_tuple<T>::value;
41
42// ============================================================================
43// Automatic Timestamp Management
44// ============================================================================
45
58// ============================================================================
59// Registry-Based Module (New Clean Interface)
60// ============================================================================
61
83// Helper to resolve MultiInputProcessorBase template arguments
84// (workaround for complex nested template parsing issues)
85// Note: Now imported from module/traits/multi_input_resolver.hpp
86
87template<typename UserRegistry,
88 typename OutputSpec_,
89 typename InputSpec_,
90 typename... CommandTypes>
91class Module
92 // ========================================================================
93 // Processing Virtual Function Providers (conditional based on I/O specs)
94 // ========================================================================
96 typename ExtractInputPayload<typename NormalizeInput<InputSpec_>::Type>::type,
97 typename ExtractOutputPayload<typename NormalizeOutput<OutputSpec_>::Type>::type
98 >
100 typename OutputTypesTuple<typename NormalizeOutput<OutputSpec_>::Type>::type,
101 typename ExtractInputPayload<typename NormalizeInput<InputSpec_>::Type>::type
102 >
104 typename ExtractInputPayload<typename NormalizeInput<InputSpec_>::Type>::type,
105 typename ExtractOutputPayload<typename NormalizeOutput<OutputSpec_>::Type>::type
106 >
107 , public ResolveMultiInputBase<InputSpec_, OutputSpec_>::type
108
109 // ========================================================================
110 // Core Module Infrastructure (CRTP mixins - always active)
111 // ========================================================================
112 , public MultiOutputManager<Module<UserRegistry, OutputSpec_, InputSpec_, CommandTypes...>, UserRegistry, typename OutputTypesTuple<typename NormalizeOutput<OutputSpec_>::Type>::type>
113 , public LoopExecutor<Module<UserRegistry, OutputSpec_, InputSpec_, CommandTypes...>>
114 , public InputMetadataAccessors<Module<UserRegistry, OutputSpec_, InputSpec_, CommandTypes...>>
115 , public CommandDispatcher<Module<UserRegistry, OutputSpec_, InputSpec_, CommandTypes...>, CommandTypes...>
116
117 // ========================================================================
118 // Multi-Input Support (conditional - only when Inputs<T,U,V> specified)
119 // ========================================================================
120 , public std::conditional_t<
121 module_traits::ModuleTypes<UserRegistry, OutputSpec_, InputSpec_>::has_multi_input,
122 MultiInputInfrastructure<Module<UserRegistry, OutputSpec_, InputSpec_, CommandTypes...>, UserRegistry, typename module_traits::ModuleTypes<UserRegistry, OutputSpec_, InputSpec_>::InputTypesTuple, module_traits::ModuleTypes<UserRegistry, OutputSpec_, InputSpec_>::InputCount>,
123 EmptyBase2
124 >
125 , public std::conditional_t<
126 module_traits::ModuleTypes<UserRegistry, OutputSpec_, InputSpec_>::has_multi_input,
127 MultiInputProcessor<Module<UserRegistry, OutputSpec_, InputSpec_, CommandTypes...>, typename module_traits::ModuleTypes<UserRegistry, OutputSpec_, InputSpec_>::InputTypesTuple, typename module_traits::ModuleTypes<UserRegistry, OutputSpec_, InputSpec_>::OutputData, typename module_traits::ModuleTypes<UserRegistry, OutputSpec_, InputSpec_>::OutputTypesTuple, module_traits::ModuleTypes<UserRegistry, OutputSpec_, InputSpec_>::InputCount>,
128 EmptyBase3
129 >
130
131 // ========================================================================
132 // Lifecycle & Infrastructure (CRTP mixins - always active)
133 // ========================================================================
134 , public LifecycleManager<Module<UserRegistry, OutputSpec_, InputSpec_, CommandTypes...>>
135 , public WorkLoopHandler<Module<UserRegistry, OutputSpec_, InputSpec_, CommandTypes...>>
136 , public MailboxInfrastructureBuilder<Module<UserRegistry, OutputSpec_, InputSpec_, CommandTypes...>, UserRegistry>
137 , public InputMetadataManager<Module<UserRegistry, OutputSpec_, InputSpec_, CommandTypes...>>
138{
139 // Friend declarations for CRTP mixins
140 friend class LoopExecutor<Module<UserRegistry, OutputSpec_, InputSpec_, CommandTypes...>>;
141 friend class MultiOutputManager<Module<UserRegistry, OutputSpec_, InputSpec_, CommandTypes...>, UserRegistry, typename OutputTypesTuple<typename NormalizeOutput<OutputSpec_>::Type>::type>;
142 friend class InputMetadataAccessors<Module<UserRegistry, OutputSpec_, InputSpec_, CommandTypes...>>;
143 friend class CommandDispatcher<Module<UserRegistry, OutputSpec_, InputSpec_, CommandTypes...>, CommandTypes...>;
144 friend class MultiInputInfrastructure<Module<UserRegistry, OutputSpec_, InputSpec_, CommandTypes...>, UserRegistry, typename module_traits::ModuleTypes<UserRegistry, OutputSpec_, InputSpec_>::InputTypesTuple, module_traits::ModuleTypes<UserRegistry, OutputSpec_, InputSpec_>::InputCount>;
145 friend class MultiInputProcessor<Module<UserRegistry, OutputSpec_, InputSpec_, CommandTypes...>, typename module_traits::ModuleTypes<UserRegistry, OutputSpec_, InputSpec_>::InputTypesTuple, typename module_traits::ModuleTypes<UserRegistry, OutputSpec_, InputSpec_>::OutputData, typename module_traits::ModuleTypes<UserRegistry, OutputSpec_, InputSpec_>::OutputTypesTuple, module_traits::ModuleTypes<UserRegistry, OutputSpec_, InputSpec_>::InputCount>;
146 friend class LifecycleManager<Module<UserRegistry, OutputSpec_, InputSpec_, CommandTypes...>>;
147 friend class WorkLoopHandler<Module<UserRegistry, OutputSpec_, InputSpec_, CommandTypes...>>;
148 friend class MailboxInfrastructureBuilder<Module<UserRegistry, OutputSpec_, InputSpec_, CommandTypes...>, UserRegistry>;
149 friend class InputMetadataManager<Module<UserRegistry, OutputSpec_, InputSpec_, CommandTypes...>>;
150
151private:
152 // ========================================================================
153 // Type Definitions
154 // ========================================================================
155
156 // Import all type computations from module_traits::ModuleTypes
157 using ModuleTypes = module_traits::ModuleTypes<UserRegistry, OutputSpec_, InputSpec_, CommandTypes...>;
158
159 // Normalized specs
160 using OutputSpec = typename ModuleTypes::OutputSpec;
161 using InputSpec = typename ModuleTypes::InputSpec;
162
163 // Type tuples
164 using OutputTypesTuple = typename ModuleTypes::OutputTypesTuple;
165 using InputTypesTuple = typename ModuleTypes::InputTypesTuple;
166 using MailboxSetTuple = typename ModuleTypes::MailboxSetTuple;
167 using CommandTuple = typename ModuleTypes::CommandTuple;
168 using CombinedCmdTypes = typename ModuleTypes::CombinedCmdTypes;
169 using DataTypesTuple = typename ModuleTypes::DataTypesTuple;
170
171 // Mailbox types
172 using CmdMailbox = typename ModuleTypes::CmdMailbox;
173 using WorkMailbox = typename ModuleTypes::WorkMailbox;
174 using PublishMailbox = typename ModuleTypes::PublishMailbox;
175 using DataMailbox = typename ModuleTypes::DataMailbox;
176
177 // Counts and flags
178 static constexpr size_t num_output_types = ModuleTypes::num_output_types;
179 static constexpr size_t num_command_types = ModuleTypes::num_command_types;
180 static constexpr size_t InputCount = ModuleTypes::InputCount;
181 static constexpr bool has_multi_input = ModuleTypes::has_multi_input;
182 static constexpr bool use_mailbox_sets = ModuleTypes::use_mailbox_sets;
183 static constexpr bool has_primary_input_spec = ModuleTypes::has_primary_input_spec;
184 using PrimaryPayloadType = typename ModuleTypes::PrimaryPayloadType;
185
186 // Compile-time validation: If PrimaryInput<T> specified, T must be in Inputs<...>
187 template<typename Dummy = void>
188 struct ValidatePrimaryInputImpl {
189 static constexpr bool check() {
190 if constexpr (has_primary_input_spec && has_multi_input) {
191 // This will trigger PrimaryInputIndex's static_assert if type not found
192 return PrimaryInputIndex_v<PrimaryPayloadType, InputTypesTuple> >= 0;
193 }
194 return true;
195 }
196 static constexpr bool value = check();
197 };
198 static_assert(ValidatePrimaryInputImpl<>::value,
199 "PrimaryInput validation failed - see error above for details");
200
201public:
202 // Public type aliases (user-visible)
205
206 // Input mode flags
211
212protected:
214
215 // Mailbox infrastructure: Tuple of MailboxSets (one per output type)
216 // Single-output modules have a tuple with 1 MailboxSet
217 // Multi-output modules have a tuple with N MailboxSets
218 MailboxSetTuple mailbox_infrastructure_;
219
220 // Helper accessors - always use first MailboxSet
221 CmdMailbox& cmd_mailbox() {
222 return *std::get<0>(mailbox_infrastructure_).cmd;
223 }
224
225 WorkMailbox& work_mailbox() {
226 return *std::get<0>(mailbox_infrastructure_).work;
227 }
228
229 PublishMailbox& publish_mailbox() {
230 static_assert(num_output_types == 1, "publish_mailbox() accessor only available for single-output modules. Use get_publish_mailbox<Index>() for multi-output");
231 return *std::get<0>(mailbox_infrastructure_).publish;
232 }
233
234 // Get specific MailboxSet by index
235 template<std::size_t Index>
237 return std::get<Index>(mailbox_infrastructure_);
238 }
239
240 // Get publish mailbox by index
241 template<std::size_t Index>
243 return *std::get<Index>(mailbox_infrastructure_).publish;
244 }
245
246 // Get work mailbox by index
247 template<std::size_t Index>
249 return *std::get<Index>(mailbox_infrastructure_).work;
250 }
251
252 // Get cmd mailbox by index
253 template<std::size_t Index>
255 return *std::get<Index>(mailbox_infrastructure_).cmd;
256 }
257
258 // Multi-input support
259 // Single-input mode
260 std::optional<DataMailbox> data_mailbox_; // base + 48: Receives input data (only for single Input<T>)
261
262 // Multi-input mailbox infrastructure (in MultiInputInfrastructure mixin)
263 // - input_mailboxes_: Tuple of HistoricalMailbox instances
264 // - secondary_input_threads_: Background receive threads
265
266 // Subscription protocol
268 UserRegistry,
270 has_multi_input,
271 InputData,
272 InputTypesTuple,
275 OutputTypesTuple
276 >;
278
279 // Publishing logic (post-unification: uses MultiOutputManager for subscribers)
281 UserRegistry,
282 OutputData,
283 PublishMailbox,
284 Module<UserRegistry, OutputSpec_, InputSpec_, CommandTypes...> // Module type for get_publish_mailbox<Index>()
285 >;
287
288 std::atomic<bool> running_;
289
290 // Module threads
291 std::optional<std::thread> data_thread_; // Periodic/loop/continuous/multi-input processing
292 std::optional<std::thread> command_thread_; // User commands on CMD mailbox
293 // Work threads: output_work_threads_ in MultiOutputManager mixin (ALL modules)
294 // Secondary input threads: secondary_input_threads_ in MultiInputInfrastructure mixin
295
296 // Subscriber management - inherited from MultiOutputManager mixin
297 // ALL modules now use per-output subscriber lists (post-unification):
298 // - output_subscribers_: Per-output subscriber lists (index 0 for single-output)
299 // - output_subscribers_mutex_: Protects output_subscribers_
300
301 // ========================================================================
302 // Input Metadata Storage
303 // ========================================================================
304
314 // Calculate number of inputs at compile time
315 static constexpr std::size_t num_inputs = InputCount_v<InputSpec>;
316
317 // Fixed-size array for input metadata (zero-size when no inputs)
319
320 // Input metadata management (in InputMetadataManager mixin)
321 // - update_input_metadata<T>()
322 // - mark_input_invalid()
323
324 // Mailbox infrastructure creation (in MailboxInfrastructureBuilder mixin)
325 // - create_mailbox_infrastructure()
326 // - create_mailbox_sets_impl()
327 // - create_mailbox_set()
328
329 // Helper: Initialize mailbox infrastructure in place
330 template<std::size_t... Is>
331 void initialize_mailbox_infrastructure_impl(const ModuleConfig& config, std::index_sequence<Is...>) {
332 // Initialize each MailboxSet in the tuple
333 ((std::get<Is>(mailbox_infrastructure_).initialize(config)), ...);
334 }
335
336public:
337 explicit Module(const ModuleConfig& config)
338 : config_(config)
339 , mailbox_infrastructure_{} // Default construct, will initialize in body
340 , data_mailbox_(has_continuous_input && !has_multi_input ?
341 std::make_optional<DataMailbox>(MailboxConfig{
342 .mailbox_id = commrat::get_mailbox_address<OutputData, OutputTypesTuple, UserRegistry>(
343 config.has_multi_output_config() ? config.system_id(0) : config.system_id(),
344 config.has_multi_output_config() ? config.instance_id(0) : config.instance_id(),
345 static_cast<uint8_t>(MailboxType::DATA)),
346 .message_slots = config.message_slots,
347 .max_message_size = UserRegistry::max_message_size,
348 .send_priority = static_cast<uint8_t>(config.priority),
349 .realtime = config.realtime,
350 .mailbox_name = config.name + "_data"
351 }) :
352 std::nullopt)
353 , running_(false)
354 {
355 // Initialize mailbox infrastructure in place
356 initialize_mailbox_infrastructure_impl(config, std::make_index_sequence<num_output_types>{});
357
358 // Initialize per-output subscriber lists (MultiOutputManager)
360
361 // Initialize subscription protocol
362 subscription_protocol_.set_config(&config_);
365
366 // Initialize publisher (post-unification: uses module_ptr_ for mailboxes and subscribers)
367 // REMOVED: set_subscriber_manager() - subscribers accessed via module_ptr_->get_output_subscribers()
368 publisher_.set_module_ptr(this); // For mailbox/subscriber access via module_ptr_
370
371 // Initialize multi-input mailboxes
372 if constexpr (has_multi_input) {
373 this->initialize_multi_input_mailboxes();
374 }
375 }
376
377 virtual ~Module() {
378 this->stop();
379 }
380
381 Module(const Module&) = delete;
382 Module& operator=(const Module&) = delete;
383 Module(Module&&) = delete;
384 Module& operator=(Module&&) = delete;
385
386 // ========================================================================
387 // Lifecycle Hooks (Override These)
388 // ========================================================================
389
390 virtual void on_init() {}
391 virtual void on_start() {}
392 virtual void on_stop() {}
393 virtual void on_cleanup() {}
394
395 // ========================================================================
396 // Processing Hooks (Override Based on InputMode)
397 // ========================================================================
398
399protected:
400 // For Input<T> with single output: process input and populate output reference
401 // Calls process which derived classes should override
402 // SFINAE: Only enabled for single output (not void, not tuple)
403 // Uses dummy template parameter O to delay evaluation until instantiation
404 template<typename T = InputData, typename O = OutputData,
405 typename = std::enable_if_t<!std::is_void_v<O> && !is_tuple_v<O>>>
406 void process_dispatch(const T& input, O& output) {
407 // this->process will resolve to derived class version
408 this->process(input, output);
409 }
410
411 // Derived classes define this (non-template) for continuous input:
412 // void process(const InputData& input, OutputData& output) { ... }
413
414
415public:
416 // ========================================================================
417 // Public Mailbox Accessors
418 // ========================================================================
419
423 template<std::size_t Index>
425 return *std::get<Index>(mailbox_infrastructure_).publish;
426 }
427
432 template<std::size_t Index>
434 return *std::get<Index>(mailbox_infrastructure_).cmd;
435 }
436
437 // ========================================================================
438 // Lifecycle Management
439 // ========================================================================
440 // start(), stop(), is_running() in LifecycleManager mixin
441
442 // ========================================================================
443 // Subscription Protocol (delegated to SubscriptionProtocol member)
444 // ========================================================================
445protected:
449
450 void subscribe_to_source(uint8_t source_system_id, uint8_t source_instance_id) {
451 subscription_protocol_.subscribe_to_source(source_system_id, source_instance_id);
452 }
453
454 void unsubscribe_from_source(uint8_t source_system_id, uint8_t source_instance_id) {
455 subscription_protocol_.unsubscribe_from_source(source_system_id, source_instance_id);
456 }
457
461
462public:
463 // Subscription protocol handlers - PUBLIC for SubscriptionProtocol callbacks
464 void handle_subscribe_request(const SubscribeRequestPayload& req, std::size_t output_idx = 0) {
465 subscription_protocol_.handle_subscribe_request(req, *this, output_idx);
466 }
467
471
475
482 void add_subscriber_to_output(uint32_t subscriber_base_addr, uint8_t mailbox_index, std::size_t output_idx = 0) {
483 // Delegate to inherited MultiOutputManager::add_subscriber_to_output
484 this->MultiOutputManager<Module<UserRegistry, OutputSpec_, InputSpec_, CommandTypes...>, UserRegistry, OutputTypesTuple>::add_subscriber_to_output(subscriber_base_addr, mailbox_index, output_idx);
485 }
486
493 void remove_subscriber(uint32_t subscriber_base_addr) {
494 // Delegate to inherited MultiOutputManager::remove_subscriber
495 this->MultiOutputManager<Module<UserRegistry, OutputSpec_, InputSpec_, CommandTypes...>, UserRegistry, OutputTypesTuple>::remove_subscriber(subscriber_base_addr);
496 }
497
498protected:
499
500 // ========================================================================
501 // Publishing
502 // ========================================================================
503 // Delegation wrappers for publishing operations
504
505 template<typename T = OutputData>
506 requires (!std::is_void_v<T>)
510
511 template<typename T>
515
516 template<typename... Ts>
517 void publish_multi_outputs(std::tuple<Ts...>& outputs) {
519 }
520
521 template<typename... Ts>
522 void publish_multi_outputs_with_timestamp(std::tuple<Ts...>& outputs, uint64_t timestamp_ns) {
524 }
525
526 template<typename T>
527 static TimsMessage<T> create_tims_message(T&& payload, uint64_t timestamp_ns) {
528 return PublisherType::create_tims_message(std::forward<T>(payload), timestamp_ns);
529 }
530
531 // ========================================================================
532 // Main Loops
533 // ========================================================================
534 // See: commrat/module/lifecycle/loop_executor.hpp
535 // - periodic_loop(): Time-driven generation (PeriodicInput)
536 // - free_loop(): Maximum throughput (LoopInput)
537 // - continuous_loop(): Event-driven single input (Input<T>)
538 // - multi_input_loop(): Synchronized multi-input (Inputs<T,U,V>)
539 // ========================================================================
540
541private:
542 // secondary_input_receive_loop() in MultiInputInfrastructure mixin
543 // command_loop() in CommandDispatcher mixin
544 // work_loop() in WorkLoopHandler mixin
545 // output_work_loop() in MultiOutputManager mixin
546 // handle_user_command() and on_command() in CommandDispatcher mixin
547
548 // ========================================================================
549 // Helper Functions
550 // ========================================================================
551
552private:
553 // Helper: Get primary input index at compile time
554 static constexpr size_t get_primary_input_index() {
555 // Extract primary input from CommandTypes (PrimaryInput<T> passed as command)
556 if constexpr (has_primary_input_spec) {
557 // PrimaryInput<T> found in CommandTypes, extract T and find index
558 return PrimaryInputIndex_v<PrimaryPayloadType, InputTypesTuple>;
559 } else {
560 // No explicit PrimaryInput - use first input as primary
561 return 0;
562 }
563 }
564
565 // Multi-input mailbox creation/initialization (in MultiInputInfrastructure mixin)
566 // - create_historical_mailbox_for_input<Index>()
567 // - create_input_mailboxes_impl()
568 // - initialize_multi_input_mailboxes()
569 // - start_input_mailboxes_impl()
570 // - start_input_mailboxes()
571 // - start_secondary_input_threads()
572 // - start_secondary_threads_impl()
573
574 // Multi-input processing (in MultiInputProcessor mixin)
575 // - receive_primary_input<PrimaryIdx>()
576 // - gather_all_inputs<PrimaryIdx>()
577 // - sync_secondary_inputs<PrimaryIdx>()
578 // - sync_secondary_inputs_impl<PrimaryIdx>()
579 // - sync_input_at_index<Index>()
580 // - call_multi_input_process()
581 // - call_multi_input_process_impl()
582 // - call_multi_input_multi_output_process()
583 // - call_multi_input_multi_output_process_impl()
584};
585
586} // namespace commrat
Command dispatcher mixin.
virtual void process(const ExtractInputPayload< NormalizeInput< InputSpec_ >::Type >::type &input, ExtractOutputPayload< NormalizeOutput< OutputSpec_ >::Type >::type &output)
Mixin providing input metadata accessor methods.
Phase 9: Input Metadata Manager CRTP Mixin.
Phase 6: Lifecycle Management CRTP Mixin.
Loop execution logic for Module data threads.
Phase 8: Mailbox Infrastructure Builder.
Timestamp Management Architecture.
void initialize_mailbox_infrastructure_impl(const ModuleConfig &config, std::index_sequence< Is... >)
void handle_unsubscribe_request(const UnsubscribeRequestPayload &req)
void handle_subscribe_request(const SubscribeRequestPayload &req, std::size_t output_idx=0)
auto & get_publish_mailbox_public()
Get publish mailbox by index (public for Publisher access)
Module(const ModuleConfig &config)
void handle_subscribe_reply(const SubscribeReplyPayload &reply)
typename ModuleTypes::OutputData OutputData
static constexpr std::size_t num_inputs
Storage for input message metadata.
PublishMailbox & publish_mailbox()
void remove_subscriber(uint32_t subscriber_base_addr)
Remove subscriber (for unsubscribe)
CmdMailbox & cmd_mailbox()
MailboxSetTuple mailbox_infrastructure_
typename ModuleTypes::InputData InputData
std::atomic< bool > running_
void publish_multi_outputs_with_timestamp(std::tuple< Ts... > &outputs, uint64_t timestamp_ns)
virtual void on_stop()
PublisherType publisher_
void unsubscribe_from_multi_input_source(const MultiInputConfig::InputSource &source)
void add_subscriber_to_output(uint32_t subscriber_base_addr, uint8_t mailbox_index, std::size_t output_idx=0)
Add subscriber to correct output-specific list.
std::optional< std::thread > command_thread_
static TimsMessage< T > create_tims_message(T &&payload, uint64_t timestamp_ns)
virtual void on_init()
static constexpr bool has_periodic_input
SubscriptionProtocolType subscription_protocol_
virtual void on_cleanup()
void unsubscribe_from_source(uint8_t source_system_id, uint8_t source_instance_id)
void subscribe_to_source(uint8_t source_system_id, uint8_t source_instance_id)
void publish_to_subscribers(T &data)
Module(Module &&)=delete
static constexpr bool has_loop_input
auto & get_cmd_mailbox_public()
Get cmd mailbox by index (public for Publisher access) Phase 7: CMD mailbox used for publishing.
std::optional< std::thread > data_thread_
virtual void on_start()
std::array< InputMetadataStorage,(num_inputs > 0 ? num_inputs :1)> input_metadata_
WorkMailbox & work_mailbox()
void process_dispatch(const T &input, O &output)
void publish_multi_outputs(std::tuple< Ts... > &outputs)
Module & operator=(const Module &)=delete
std::optional< DataMailbox > data_mailbox_
static constexpr bool has_continuous_input
Module(const Module &)=delete
static constexpr bool has_multi_output
Module & operator=(Module &&)=delete
void publish_tims_message(TimsMessage< T > &tims_msg)
Multi-input infrastructure mixin.
Multi-input processing mixin.
CRTP mixin for multi-output mailbox and subscriber management.
void set_module_name(const std::string &name)
void publish_multi_outputs(std::tuple< Ts... > &outputs)
Publish multiple outputs (tuple) to subscribers Each subscriber receives only outputs matching their ...
void publish_to_subscribers(T &data)
Single-output publishing (only enabled when OutputData is not void) Publishes data to all subscribers...
static TimsMessage< T > create_tims_message(T &&payload, uint64_t timestamp_ns)
Create TimsMessage with explicit timestamp Phase 6.10: Single source of truth for timestamps (header....
void set_module_ptr(ModuleType *ptr)
void publish_tims_message(TimsMessage< T > &tims_msg)
Publish TimsMessage<T> for single output Phase 6.10: Uses explicit timestamp from header Phase 7: Use...
void publish_multi_outputs_with_timestamp(std::tuple< Ts... > &outputs, uint64_t timestamp_ns)
Publish multi-outputs with explicit timestamp Phase 6.10: Wraps each output in TimsMessage with times...
Mailbox that takes a MessageRegistry and exposes payload-only interface.
void handle_subscribe_reply(const SubscribeReplyType &reply)
Handle incoming SubscribeReply (consumer side)
void subscribe_to_source(uint8_t source_system_id, uint8_t source_instance_id)
Legacy single-input subscription (backward compatible)
void unsubscribe_from_multi_input_source(const MultiInputConfig::InputSource &source)
Unsubscribe from multi-input source.
void handle_subscribe_request(const SubscribeRequestType &req, SubscriberMgr &sub_mgr, std::size_t output_idx=0)
Handle incoming SubscribeRequest (producer side)
void handle_unsubscribe_request(const UnsubscribeRequestType &req, SubscriberMgr &sub_mgr)
Handle incoming UnsubscribeRequest (producer side)
void unsubscribe_from_source(uint8_t source_system_id, uint8_t source_instance_id)
Unsubscribe from single-input source.
void set_module_name(const std::string &name)
void set_config(const ModuleConfig *cfg)
void subscribe_to_all_sources()
Subscribe to all configured input sources.
void set_work_mailbox(RegistryMailbox< SystemRegistry > *mbx)
Phase 7: Work Loop Handler CRTP Mixin.
RegistryMailbox wrapper with timestamped history for multi-input synchronization (Phase 6....
Core module infrastructure - type traits, specs, and configuration.
CRTP mixins that compose Module functionality.
Module service components - subscription and publishing.
CommRaT - Modern C++ Real-Time Communication Framework.
constexpr bool is_tuple_v
static constexpr uint32_t get_mailbox_address(uint8_t system_id, uint8_t instance_id, uint8_t mailbox_index)
Get specific mailbox address with index.
Get the number of inputs in an InputSpec.
Definition io_spec.hpp:376
Storage for input message metadata.
Maps raw output types to Output<T> format.
Definition io_spec.hpp:414
Reply to subscription request.
Request to subscribe to continuous data from a producer module.
Request to unsubscribe from continuous data.
Centralized type computation for Module class.
NormalizeOutput_t< OutputSpec_ > OutputSpec
static constexpr bool has_multi_output
typename ExtractInputTypes< InputSpec >::type InputTypesTuple
NormalizeInput_t< InputSpec_ > InputSpec
static constexpr size_t num_command_types
static constexpr size_t InputCount
static constexpr bool has_periodic_input
typename ExtractPrimaryPayloadHelper< CommandTypes... >::type PrimaryPayloadType
typename MakeTypedCmdMailbox< UserRegistry, OutputTypesTuple >::type PublishMailbox
typename MakeTypedCmdMailboxWithSend< UserRegistry, CommandTuple, OutputTypesTuple >::type CmdMailbox
static constexpr bool has_continuous_input
typename ExtractDataTypes< InputSpec >::type DataTypesTuple
static constexpr bool has_primary_input_spec
static constexpr bool use_mailbox_sets
typename ExtractInputPayload< InputSpec >::type InputData
typename MakeTypedDataMailbox< UserRegistry, DataTypesTuple >::type DataMailbox
std::tuple< CommandTypes... > CommandTuple
typename MakeMailboxSetTuple< UserRegistry, OutputTypesTuple, CommandTypes... >::type MailboxSetTuple
static constexpr size_t num_output_types
typename ::commrat::OutputTypesTuple< OutputSpec >::type OutputTypesTuple
static constexpr bool has_multi_input
decltype(std::tuple_cat(std::declval< CommandTuple >(), std::declval< OutputTypesTuple >())) CombinedCmdTypes
typename ExtractOutputPayload< OutputSpec >::type OutputData
Unified threading and synchronization abstractions for CommRaT.
Unified timestamp and time utility abstractions for CommRaT.
Type-restricted mailbox with optimized buffer sizing (Phase 7)