SObjectizer-5 Extra
Loading...
Searching...
No Matches
send_functions.hpp
Go to the documentation of this file.
1/*!
2 * \file
3 * \brief Variuos send functions for simplification of sending
4 * enveloped messages.
5 *
6 * \since
7 * v.1.2.0
8 */
9
10#pragma once
11
12#include <so_5/version.hpp>
13
14#if SO_5_VERSION < SO_5_VERSION_MAKE(5, 8, 1)
15#error "SObjectizer v.5.8.1 or above required"
16#endif
17
18#include <so_5_extra/enveloped_msg/errors.hpp>
19
20#include <so_5/send_functions.hpp>
21
22#include <so_5/optional.hpp>
23
24namespace so_5 {
25
26namespace extra {
27
28namespace enveloped_msg {
29
30namespace details {
31
32/*!
33 * \brief Internal type that holds a message before it will be enveloped.
34 *
35 * This type provides such methods as:
36 * - envelope() for creation of new envelope;
37 * - send_to for sending of ordinary message to the specified mbox (mchain);
38 * - send_delayed_to for sending of delayed message;
39 * - send_periodic_to for sending of periodic message.
40 *
41 * \note
42 * Object of type payload_holder_t can be in two states: full and empty.
43 * When object is full then envelope() creates an envelope and switches
44 * the object to empty state. If envelope() is called in empty state
45 * an exeception is thrown.
46 *
47 * \since
48 * v.1.2.0
49 */
50class payload_holder_t final
51 {
52 struct data_t final
53 {
55 // Can be null pointer in the case of error.
57 };
58
60
61 void
63 const char * context_name ) const
64 {
65 if( !m_data )
66 SO_5_THROW_EXCEPTION(
67 errors::rc_empty_payload_holder,
68 std::string( "empty payload_holder can't be used for: " ) +
69 context_name );
70 }
71
72 public :
74 std::type_index msg_type,
75 message_ref_t message )
77 {}
78
79 payload_holder_t( const payload_holder_t & ) = delete;
80
81 payload_holder_t( payload_holder_t && ) = default;
82 payload_holder_t & operator=( payload_holder_t && ) = default;
83
84 template< typename Envelope, typename... Args >
85 [[nodiscard]]
86 payload_holder_t
87 envelope( Args && ...args )
88 {
89 ensure_not_empty_object( "envelope()" );
90
91 message_ref_t envelope{
92 std::make_unique< Envelope >(
93 m_data->m_message,
94 std::forward<Args>(args)... )
95 };
96
97 payload_holder_t result{
98 m_data->m_msg_type,
99 std::move(envelope)
100 };
101
102 // Now data can be dropped. Payload holder becomes empty.
103 m_data.reset();
104
105 return result;
106 }
107
108 template< typename Target >
109 void
110 send_to( Target && to )
111 {
112 ensure_not_empty_object( "send_to()" );
113
114 // NOTE: there is no need to check mutability of a message.
115 // This check should be performed by the target mbox itself.
116 so_5::send_functions_details::arg_to_mbox( to )->
117 do_deliver_message(
118 so_5::message_delivery_mode_t::ordinary,
119 m_data->m_msg_type,
120 m_data->m_message,
121 1u );
122 }
123
124 void
126 const so_5::mbox_t & to,
127 std::chrono::steady_clock::duration pause )
128 {
129 ensure_not_empty_object( "send_delayed_to()" );
130
131 so_5::low_level_api::single_timer(
132 m_data->m_msg_type,
133 m_data->m_message,
134 to,
135 pause );
136 }
137
138 template< typename Target >
139 void
141 Target && to,
142 std::chrono::steady_clock::duration pause )
143 {
144 return this->send_delayed_to(
145 so_5::send_functions_details::arg_to_mbox( to ),
146 pause );
147 }
148
149 [[nodiscard]]
150 auto
152 const so_5::mbox_t & to,
153 std::chrono::steady_clock::duration pause,
154 std::chrono::steady_clock::duration period )
155 {
156 ensure_not_empty_object( "send_periodic_to()" );
157
158 return so_5::low_level_api::schedule_timer(
159 m_data->m_msg_type,
160 m_data->m_message,
161 to,
162 pause,
163 period );
164 }
165
166 template< typename Target >
167 [[nodiscard]]
168 auto
170 Target && to,
171 std::chrono::steady_clock::duration pause,
172 std::chrono::steady_clock::duration period )
173 {
174 return this->send_periodic_to(
175 so_5::send_functions_details::arg_to_mbox( to ),
176 pause,
177 period );
178 }
179 };
180
181} /* namespace details */
182
183/*!
184 * \brief A special message builder that allows to wrap a message into an
185 * envelope.
186 *
187 * This function creates an instance of a specified message type and creates
188 * a chain of builders that envelope this instance into an envelope and send
189 * the enveloped message as ordinary or delayed/periodic message.
190 *
191 * Usage examples:
192 * \code
193 * namespace msg_ns = so_5::extra::enveloped_msg;
194 *
195 * // Create message of type my_message, envelop it into my_envelope
196 * // and then send it to the mbox mb1.
197 * so_5::mbox_t mb1 = ...;
198 * msg_ns::make<my_message>(...)
199 * .envelope<my_envelope>(...)
200 * .send_to(mb1);
201 *
202 * // Create message of type my_message, envelop it into my_envelope
203 * // and then send it to the mchain ch1.
204 * so_5::mchain_t ch1 = ...;
205 * msg_ns::make<my_message>(...)
206 * .envelope<my_envelope>(...)
207 * .send_to(ch1);
208 *
209 * // Create message of type my_message, envelop it into my_envelope
210 * // and then send it to the direct mbox of the agent a1.
211 * so_5::agent_t & a1 = ...;
212 * msg_ns::make<my_message>(...)
213 * .envelope<my_envelope>(...)
214 * .send_to(a1);
215 *
216 * // Create message of type my_message, envelop it into my_envelope
217 * // and then send it to the mbox mb1 as delayed message.
218 * so_5::mbox_t mb1 = ...;
219 * msg_ns::make<my_message>(...)
220 * .envelope<my_envelope>(...)
221 * .send_delayed_to(mb1, 10s);
222 *
223 * // Create message of type my_message, envelop it into my_envelope
224 * // and then send it to the mchain ch1 as delayed message.
225 * so_5::mchain_t ch1 = ...;
226 * msg_ns::make<my_message>(...)
227 * .envelope<my_envelope>(...)
228 * .send_delayed_to(ch1, 10s);
229 *
230 * // Create message of type my_message, envelop it into my_envelope
231 * // and then send it to the direct mbox of the agent a1 as delayed message.
232 * so_5::agent_t & a1 = ...;
233 * msg_ns::make<my_message>(...)
234 * .envelope<my_envelope>(...)
235 * .send_delayed_to(a1, 10s);
236 *
237 * // Create message of type my_message, envelop it into my_envelope
238 * // and then send it to the mbox mb1 as periodic message.
239 * so_5::mbox_t mb1 = ...;
240 * auto timer_id = msg_ns::make<my_message>(...)
241 * .envelope<my_envelope>(...)
242 * .send_periodic_to(mb1, 10s, 30s);
243 *
244 * // Create message of type my_message, envelop it into my_envelope
245 * // and then send it to the mchain ch1 as delayed message.
246 * so_5::mchain_t ch1 = ...;
247 * auto timer_id = msg_ns::make<my_message>(...)
248 * .envelope<my_envelope>(...)
249 * .send_periodic_to(ch1, 10s, 30s);
250 *
251 * // Create message of type my_message, envelop it into my_envelope
252 * // and then send it to the direct mbox of the agent a1 as delayed message.
253 * so_5::agent_t & a1 = ...;
254 * auto timer_id = msg_ns::make<my_message>(...)
255 * .envelope<my_envelope>(...)
256 * .send_periodic_to(a1, 10s, 30s);
257 * \endcode
258 *
259 * \since
260 * v.1.2.0
261 */
262template< typename Message, typename... Args >
263[[nodiscard]]
264details::payload_holder_t
265make( Args && ...args )
266 {
267 // Since SO-5.8.1 mutability is handled by make_message_instance.
270 std::forward<Args>(args)... )
271 };
272
273 return {
276 };
277 }
278
279} /* namespace enveloped_msg */
280
281} /* namespace extra */
282
283} /* namespace so_5 */
payload_holder_t(std::type_index msg_type, message_ref_t message)
payload_holder_t(const payload_holder_t &)=delete
payload_holder_t & operator=(payload_holder_t &&)=default
auto send_periodic_to(const so_5::mbox_t &to, std::chrono::steady_clock::duration pause, std::chrono::steady_clock::duration period)
void send_delayed_to(const so_5::mbox_t &to, std::chrono::steady_clock::duration pause)
auto send_periodic_to(Target &&to, std::chrono::steady_clock::duration pause, std::chrono::steady_clock::duration period)
void send_delayed_to(Target &&to, std::chrono::steady_clock::duration pause)
void ensure_not_empty_object(const char *context_name) const
details::payload_holder_t make(Args &&...args)
A special message builder that allows to wrap a message into an envelope.
Ranges for error codes of each submodules.
Definition details.hpp:13