CommRaT 2.0.0
C++20 Real-Time Messaging Framework
Loading...
Searching...
No Matches
registry_mailbox.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "mailbox.hpp"
4#include "../messaging/message_registry.hpp"
5#include "../platform/threading.hpp"
6
7namespace commrat {
8
9// ============================================================================
10// Registry-Based Mailbox (User-Friendly Interface)
11// ============================================================================
12
38template<typename Registry>
40private:
41 // Extract MessageDefinition types from registry to create underlying Mailbox type
42 template<typename... MessageDefs>
43 static Mailbox<MessageDefs...> extract_defs(MessageRegistry<MessageDefs...>*);
44
45 using UnderlyingMailbox = decltype(extract_defs(static_cast<Registry*>(nullptr)));
46
47 UnderlyingMailbox mailbox_;
48
49public:
50 // ========================================================================
51 // Construction and Lifecycle (Same as Mailbox)
52 // ========================================================================
53
54 explicit RegistryMailbox(const MailboxConfig& config)
55 : mailbox_(config) {}
56
57 ~RegistryMailbox() = default;
58
59 // Non-copyable, movable
62 RegistryMailbox(RegistryMailbox&&) noexcept = default;
63 RegistryMailbox& operator=(RegistryMailbox&&) noexcept = default;
64
65 // ========================================================================
66 // Lifecycle Management
67 // ========================================================================
68
69 auto start() -> MailboxResult<void> {
70 return mailbox_.start();
71 }
72
73 void stop() {
74 mailbox_.stop();
75 }
76
77 bool is_running() const {
78 return mailbox_.is_running();
79 }
80
81 uint32_t mailbox_id() const {
82 return mailbox_.mailbox_id();
83 }
84
85 // ========================================================================
86 // Type Validation (Payload Types)
87 // ========================================================================
88
89 template<typename PayloadT>
90 static constexpr bool is_registered = Registry::template is_registered<PayloadT>;
91
92 static constexpr size_t num_message_types() {
93 return Registry::size();
94 }
95
96 // ========================================================================
97 // Send Operations (Payload Types Only)
98 // ========================================================================
99
110 template<typename PayloadT>
111 requires is_registered<PayloadT>
112 auto send(PayloadT& payload, uint32_t dest_mailbox) -> MailboxResult<void> {
113 // Create TimsMessage wrapper
115 .header = {
116 .msg_type = Registry::template get_message_id<PayloadT>(),
117 .msg_size = 0, // Will be set by serialization
118 .timestamp = 0, // Will be set by TiMS
119 .seq_number = 0, // Will be set by TiMS
120 .flags = 0
121 },
122 .payload = payload
123 };
124
125 return mailbox_.send(msg, dest_mailbox);
126 }
127
139 template<typename PayloadT>
140 requires is_registered<PayloadT>
141 auto send(PayloadT& payload, uint32_t dest_mailbox, uint64_t timestamp) -> MailboxResult<void> {
142 // Create TimsMessage wrapper with explicit timestamp
144 .header = {
145 .msg_type = Registry::template get_message_id<PayloadT>(),
146 .msg_size = 0, // Will be set by serialization
147 .timestamp = timestamp, // USER-PROVIDED timestamp
148 .seq_number = 0, // Will be set by TiMS
149 .flags = 0
150 },
151 .payload = payload
152 };
153
154 return mailbox_.send(msg, dest_mailbox);
155 }
156
157 // ========================================================================
158 // Receive Operations (Payload Types Only)
159 // ========================================================================
160
164 template<typename PayloadT>
165 requires is_registered<PayloadT>
167 return mailbox_.template receive<PayloadT>();
168 }
169
173 template<typename PayloadT>
174 requires is_registered<PayloadT>
176 return mailbox_.template try_receive<PayloadT>();
177 }
178
182 template<typename PayloadT>
183 requires is_registered<PayloadT>
184 auto receive_for(std::chrono::milliseconds timeout) -> MailboxResult<TimsMessage<PayloadT>> {
185 return mailbox_.template receive_for<PayloadT>(timeout);
186 }
187
193 template<typename Visitor>
194 auto receive_any(Visitor&& visitor) -> MailboxResult<void> {
195 return mailbox_.receive_any(std::forward<Visitor>(visitor));
196 }
197
198 template<typename Visitor>
199 auto try_receive_any(Visitor&& visitor) -> MailboxResult<void> {
200 return mailbox_.try_receive_any(std::forward<Visitor>(visitor));
201 }
202
203 template<typename Visitor>
204 auto receive_any_for(std::chrono::milliseconds timeout, Visitor&& visitor) -> MailboxResult<void> {
205 // Poll with non-blocking receives and short sleeps to avoid TiMS timeout quirk
206 auto start = std::chrono::steady_clock::now();
207 while (std::chrono::steady_clock::now() - start < timeout) {
208 // Non-blocking receive (timeout = -1ms)
209 auto result = mailbox_.receive_any_raw(std::chrono::milliseconds{-1});
210 if (result) {
211 // Use Registry::visit to deserialize and dispatch
212 bool handled = Registry::visit(
213 static_cast<uint32_t>(result->type),
214 std::span{result->buffer.data(), result->buffer.size()},
215 [&](auto& tims_msg) {
216 // Registry::visit deserializes to TimsMessage<PayloadT>
217 // Pass it directly to visitor
218 visitor(tims_msg);
219 }
220 );
221
222 if (handled) {
224 }
225 }
226 // Sleep longer to reduce busy-waiting CPU usage
227 std::this_thread::sleep_for(std::chrono::milliseconds(10));
228 }
230 }
231
232 // ========================================================================
233 // Direct Access to Underlying Mailbox (If Needed)
234 // ========================================================================
235
236 UnderlyingMailbox& underlying() { return mailbox_; }
237 const UnderlyingMailbox& underlying() const { return mailbox_; }
238};
239
240// ============================================================================
241// Convenience Factory Function
242// ============================================================================
243
244template<typename Registry>
245auto make_mailbox(const MailboxConfig& config) {
246 return RegistryMailbox<Registry>(config);
247}
248
249} // namespace commrat
MailboxError error() const
Definition mailbox.hpp:86
Strongly-typed mailbox for message-based communication.
Definition mailbox.hpp:177
Compile-time message type registry using MessageDefinition templates.
Mailbox that takes a MessageRegistry and exposes payload-only interface.
auto receive_for(std::chrono::milliseconds timeout) -> MailboxResult< TimsMessage< PayloadT > >
Receive with timeout.
const UnderlyingMailbox & underlying() const
UnderlyingMailbox & underlying()
RegistryMailbox(const RegistryMailbox &)=delete
RegistryMailbox & operator=(const RegistryMailbox &)=delete
auto start() -> MailboxResult< void >
auto send(PayloadT &payload, uint32_t dest_mailbox, uint64_t timestamp) -> MailboxResult< void >
Send a message payload with explicit timestamp (Phase 6.10)
auto receive_any_for(std::chrono::milliseconds timeout, Visitor &&visitor) -> MailboxResult< void >
RegistryMailbox(RegistryMailbox &&) noexcept=default
auto try_receive() -> MailboxResult< TimsMessage< PayloadT > >
Try to receive a message (non-blocking)
auto receive() -> MailboxResult< TimsMessage< PayloadT > >
Receive a message of specific payload type (blocking)
auto send(PayloadT &payload, uint32_t dest_mailbox) -> MailboxResult< void >
Send a message payload to a destination mailbox.
static constexpr size_t num_message_types()
auto receive_any(Visitor &&visitor) -> MailboxResult< void >
Receive any registered message type using visitor pattern.
static constexpr bool is_registered
RegistryMailbox(const MailboxConfig &config)
auto try_receive_any(Visitor &&visitor) -> MailboxResult< void >
Build a complete registry with automatic Module and Mailbox aliases.
CommRaT - Modern C++ Real-Time Communication Framework.
auto make_mailbox(const MailboxConfig &config)