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