SObjectizer-5 Extra
proxy.hpp
Go to the documentation of this file.
1 /*!
2  * \file
3  * \brief Implementation of simple mbox proxy.
4  *
5  * \since
6  * v.1.2.0
7  */
8 
9 #pragma once
10 
11 #include <so_5_extra/error_ranges.hpp>
12 
13 #include <so_5/rt/h/mbox.hpp>
14 
15 #if defined(SO_5_VERSION)
16  #if (SO_5_VERSION < SO_5_VERSION_MAKE(5, 23, 0))
17  #error "SObjectizer v.5.5.23 or above is required"
18  #endif
19 #else
20  #error "SObjectizer v.5.5.23 or above is required"
21 #endif
22 
23 namespace so_5 {
24 
25 namespace extra {
26 
27 namespace mboxes {
28 
29 namespace proxy {
30 
31 namespace errors {
32 
33 /*!
34  * \brief Null pointer to underlying mbox.
35  *
36  * A proxy-mbox uses underlying mbox and delegates all actions to that mbox.
37  * Because of that underlying mbox can't be nullptr.
38  *
39  * \since
40  * v.1.2.0
41  */
44 
45 } /* namespace errors */
46 
47 //
48 // simple_t
49 //
50 /*!
51  * \brief A simple proxy that delegates all calls to underlying actual mbox.
52  *
53  * Sometimes it is necessary to create an own mbox that does
54  * some specific task. For example, counts the number of message
55  * of some specific type. Something like:
56  * \code
57  * class my_mbox final : public so_5::abstract_message_box_t
58  * {
59  * bool is_appropriate_message_type(
60  * const std::type_index & msg_type ) const { ... }
61  *
62  * std::size_t counter_{};
63  * ...
64  * void do_deliver_message(
65  * const std::type_index & msg_type,
66  * const so_5::message_ref_t & message,
67  * unsigned int overlimit_reaction_deep ) const override {
68  * if(is_appropriate_message_type(msg_type))
69  * ++counter_;
70  * ... // Actual message delivery.
71  * }
72  * };
73  * \endcode
74  * But it is hard to create a full implementation of
75  * so_5::abstract_message_box_t from the ground up. An existing mbox can be
76  * used for doing actual work:
77  * \code
78  * class my_mbox final : public so_5::abstract_message_box_t
79  * {
80  * bool is_appropriate_message_type(
81  * const std::type_index & msg_type ) const { ... }
82  *
83  * const so_5::mbox_t mbox_;
84  * std::size_t counter_{};
85  * ...
86  * public:
87  * my_mbox(so_5::mbox_t mbox) : mbox_{std::move(mbox)} {}
88  * ...
89  * void do_deliver_message(
90  * const std::type_index & msg_type,
91  * const so_5::message_ref_t & message,
92  * unsigned int overlimit_reaction_deep ) const override {
93  * if(is_appropriate_message_type(msg_type))
94  * ++counter_;
95  * // Use actual mbox for message delivery.
96  * mbox_->do_deliver_message(
97  * msg_type, message, overlimit_reaction_deep);
98  * }
99  * };
100  * \endcode
101  * But there is a small problem with this approach: so_5::abstract_message_box_t
102  * has a rich interface with a lot of pure virtual methods. It is a boring
103  * task to reimplement all of them.
104  *
105  * In such cases simple_t can be used to reduce amount of developer's work:
106  * \code
107  * class my_mbox final : public so_5::extra::mboxes::proxy::simple_t
108  * {
109  * using base_type = so_5::extra::mboxes::proxy::simple_t;
110  *
111  * bool is_appropriate_message_type(
112  * const std::type_index & msg_type ) const { ... }
113  *
114  * std::size_t counter_{};
115  *
116  * public:
117  * my_mbox(so_5::mbox_t mbox) : base_type{std::move(mbox)} {}
118  *
119  * void do_deliver_message(
120  * const std::type_index & msg_type,
121  * const so_5::message_ref_t & message,
122  * unsigned int overlimit_reaction_deep ) const override {
123  * if(is_appropriate_message_type(msg_type))
124  * ++counter_;
125  * // Use actual mbox for message delivery.
126  * base_type::do_deliver_message(
127  * msg_type, message, overlimit_reaction_deep);
128  * }
129  * }
130  * \endcode
131  * And that's all.
132  *
133  * \since
134  * v.5.5.23
135  */
137  {
138  //! Actual underlying mbox to be used for all calls.
139  /*!
140  * \attention Should not be nullptr.
141  */
143 
144  //! Ensure that underlying mbox is not nullptr.
145  /*!
146  * \throw so_5::exception_t if \a mbox is nullptr.
147  */
148  ::so_5::mbox_t
150  ::so_5::mbox_t mbox )
151  {
152  if( !mbox )
153  SO_5_THROW_EXCEPTION(
154  errors::rc_nullptr_as_underlying_mbox,
155  "nullptr is used as underlying mbox" );
156 
157  return mbox;
158  }
159 
160  protected :
161  //! An accessor to actual mbox.
162  /*!
163  * This method is intended to be used in derived classes.
164  * For example:
165  * \code
166  * class my_mbox : public so_5::extra::mboxes::proxy::simple_t {
167  * public:
168  * void do_deliver_message(
169  * const std::type_index & msg_type,
170  * const so_5::message_ref_t & message,
171  * unsigned int overlimit_reaction_deep ) const override {
172  * ... // Do some specific stuff.
173  * // Use actual mbox for message delivery.
174  * underlying_mbox().do_deliver_message(
175  * msg_type, message, overlimit_reaction_deep);
176  * }
177  * ...
178  * };
179  * \endcode
180  */
182  underlying_mbox() const noexcept
183  {
184  return *m_underlying_mbox;
185  }
186 
187  public :
188  //! Initializing constructor.
190  //! Actual underlying mbox to be used for all operations.
191  //! Must not be nullptr.
192  ::so_5::mbox_t underlying_mbox )
195  {}
196 
197  /*!
198  * \name Simple implementation of inherited methods.
199  * \{
200  */
201  mbox_id_t
202  id() const override
203  {
204  return underlying_mbox().id();
205  }
206 
207  void
209  const std::type_index & type_index,
210  const ::so_5::message_limit::control_block_t * limit,
211  ::so_5::agent_t * subscriber ) override
212  {
213  underlying_mbox().subscribe_event_handler(
214  type_index,
215  limit,
216  subscriber );
217  }
218 
219  void
221  const std::type_index & type_index,
222  ::so_5::agent_t * subscriber ) override
223  {
224  underlying_mbox().unsubscribe_event_handlers(
225  type_index,
226  subscriber );
227  }
228 
229  std::string
230  query_name() const override
231  {
232  return underlying_mbox().query_name();
233  }
234 
236  type() const override
237  {
238  return underlying_mbox().type();
239  }
240 
241  void
243  const std::type_index & msg_type,
244  const ::so_5::message_ref_t & message,
245  unsigned int overlimit_reaction_deep ) const override
246  {
247  underlying_mbox().do_deliver_message(
248  msg_type,
249  message,
250  overlimit_reaction_deep );
251  }
252 
253  void
255  const std::type_index & msg_type,
256  const ::so_5::message_ref_t & message,
257  unsigned int overlimit_reaction_deep ) const override
258  {
259  underlying_mbox().do_deliver_service_request(
260  msg_type,
261  message,
262  overlimit_reaction_deep );
263  }
264 
265  void
267  const std::type_index & msg_type,
268  const ::so_5::message_ref_t & message,
269  unsigned int overlimit_reaction_deep ) override
270  {
271  underlying_mbox().do_deliver_enveloped_msg(
272  msg_type,
273  message,
274  overlimit_reaction_deep );
275  }
276 
277  void
279  const std::type_index & msg_type,
280  const ::so_5::delivery_filter_t & filter,
281  ::so_5::agent_t & subscriber ) override
282  {
283  underlying_mbox().set_delivery_filter(
284  msg_type,
285  filter,
286  subscriber );
287  }
288 
289  void
291  const std::type_index & msg_type,
292  ::so_5::agent_t & subscriber ) noexcept override
293  {
294  underlying_mbox().drop_delivery_filter(
295  msg_type,
296  subscriber );
297  }
298 
299  protected :
300  void
302  const std::type_index & msg_type,
303  const ::so_5::message_ref_t & message ) override
304  {
305  delegate_deliver_message_from_timer(
306  underlying_mbox(),
307  msg_type,
308  message );
309  }
310  /*!
311  * \}
312  */
313  };
314 
315 } /* namespace proxy */
316 
317 } /* namespace mboxes */
318 
319 } /* namespace extra */
320 
321 } /* namespace so_5 */
void do_deliver_enveloped_msg(const std::type_index &msg_type, const ::so_5::message_ref_t &message, unsigned int overlimit_reaction_deep) override
Definition: proxy.hpp:266
void subscribe_event_handler(const std::type_index &type_index, const ::so_5::message_limit::control_block_t *limit, ::so_5::agent_t *subscriber) override
Definition: proxy.hpp:208
::so_5::abstract_message_box_t & underlying_mbox() const noexcept
An accessor to actual mbox.
Definition: proxy.hpp:182
void drop_delivery_filter(const std::type_index &msg_type, ::so_5::agent_t &subscriber) noexcept override
Definition: proxy.hpp:290
mbox_type_t type() const override
Definition: proxy.hpp:236
void do_deliver_service_request(const std::type_index &msg_type, const ::so_5::message_ref_t &message, unsigned int overlimit_reaction_deep) const override
Definition: proxy.hpp:254
Ranges for error codes of each submodules.
Definition: details.hpp:14
mbox_id_t id() const override
Definition: proxy.hpp:202
void set_delivery_filter(const std::type_index &msg_type, const ::so_5::delivery_filter_t &filter, ::so_5::agent_t &subscriber) override
Definition: proxy.hpp:278
::so_5::mbox_t ensure_underlying_mbox_not_null(::so_5::mbox_t mbox)
Ensure that underlying mbox is not nullptr.
Definition: proxy.hpp:149
void do_deliver_message(const std::type_index &msg_type, const ::so_5::message_ref_t &message, unsigned int overlimit_reaction_deep) const override
Definition: proxy.hpp:242
std::string query_name() const override
Definition: proxy.hpp:230
A simple proxy that delegates all calls to underlying actual mbox.
Definition: proxy.hpp:136
void do_deliver_message_from_timer(const std::type_index &msg_type, const ::so_5::message_ref_t &message) override
Definition: proxy.hpp:301
const int rc_nullptr_as_underlying_mbox
Null pointer to underlying mbox.
Definition: proxy.hpp:42
const ::so_5::mbox_t m_underlying_mbox
Actual underlying mbox to be used for all calls.
Definition: proxy.hpp:142
simple_t(::so_5::mbox_t underlying_mbox)
Initializing constructor.
Definition: proxy.hpp:189
void unsubscribe_event_handlers(const std::type_index &type_index, ::so_5::agent_t *subscriber) override
Definition: proxy.hpp:220