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  * so_5::message_delivery_mode_t delivery_mode,
58  * const std::type_index & msg_type,
59  * const so_5::message_ref_t & message,
60  * unsigned int redirection_deep ) override {
61  * if(is_appropriate_message_type(msg_type))
62  * ++counter_;
63  * ... // Actual message delivery.
64  * }
65  * };
66  * \endcode
67  * But it is hard to create a full implementation of
68  * so_5::abstract_message_box_t from the ground up. An existing mbox can be
69  * used for doing actual work:
70  * \code
71  * class my_mbox final : public so_5::abstract_message_box_t
72  * {
73  * bool is_appropriate_message_type(
74  * const std::type_index & msg_type ) const { ... }
75  *
76  * const so_5::mbox_t mbox_;
77  * std::size_t counter_{};
78  * ...
79  * public:
80  * my_mbox(so_5::mbox_t mbox) : mbox_{std::move(mbox)} {}
81  * ...
82  * void do_deliver_message(
83  * so_5::message_delivery_mode_t delivery_mode,
84  * const std::type_index & msg_type,
85  * const so_5::message_ref_t & message,
86  * unsigned int redirection_deep ) override {
87  * if(is_appropriate_message_type(msg_type))
88  * ++counter_;
89  * // Use actual mbox for message delivery.
90  * mbox_->do_deliver_message(
91  * delivery_mode, msg_type, message, redirection_deep);
92  * }
93  * };
94  * \endcode
95  * But there is a small problem with this approach: so_5::abstract_message_box_t
96  * has a rich interface with a lot of pure virtual methods. It is a boring
97  * task to reimplement all of them.
98  *
99  * In such cases simple_t can be used to reduce amount of developer's work:
100  * \code
101  * class my_mbox final : public so_5::extra::mboxes::proxy::simple_t
102  * {
103  * using base_type = so_5::extra::mboxes::proxy::simple_t;
104  *
105  * bool is_appropriate_message_type(
106  * const std::type_index & msg_type ) const { ... }
107  *
108  * std::size_t counter_{};
109  *
110  * public:
111  * my_mbox(so_5::mbox_t mbox) : base_type{std::move(mbox)} {}
112  *
113  * void do_deliver_message(
114  * so_5::message_delivery_mode_t delivery_mode,
115  * const std::type_index & msg_type,
116  * const so_5::message_ref_t & message,
117  * unsigned int redirection_deep ) override {
118  * if(is_appropriate_message_type(msg_type))
119  * ++counter_;
120  * // Use actual mbox for message delivery.
121  * base_type::do_deliver_message(
122  * delivery_mode, msg_type, message, redirection_deep);
123  * }
124  * }
125  * \endcode
126  * And that's all.
127  *
128  * \since
129  * v.5.5.23
130  */
132  {
133  //! Actual underlying mbox to be used for all calls.
134  /*!
135  * \attention Should not be nullptr.
136  */
138 
139  //! Ensure that underlying mbox is not nullptr.
140  /*!
141  * \throw so_5::exception_t if \a mbox is nullptr.
142  */
143  ::so_5::mbox_t
145  ::so_5::mbox_t mbox )
146  {
147  if( !mbox )
148  SO_5_THROW_EXCEPTION(
149  errors::rc_nullptr_as_underlying_mbox,
150  "nullptr is used as underlying mbox" );
151 
152  return mbox;
153  }
154 
155  protected :
156  //! An accessor to actual mbox.
157  /*!
158  * This method is intended to be used in derived classes.
159  * For example:
160  * \code
161  * class my_mbox : public so_5::extra::mboxes::proxy::simple_t {
162  * public:
163  * void do_deliver_message(
164  * so_5::message_delivery_mode_t delivery_mode,
165  * const std::type_index & msg_type,
166  * const so_5::message_ref_t & message,
167  * unsigned int redirection_deep ) override {
168  * ... // Do some specific stuff.
169  * // Use actual mbox for message delivery.
170  * underlying_mbox().do_deliver_message(
171  * delivery_mode, msg_type, message, redirection_deep);
172  * }
173  * ...
174  * };
175  * \endcode
176  */
178  underlying_mbox() const noexcept
179  {
180  return *m_underlying_mbox;
181  }
182 
183  public :
184  //! Initializing constructor.
186  //! Actual underlying mbox to be used for all operations.
187  //! Must not be nullptr.
188  ::so_5::mbox_t underlying_mbox )
191  {}
192 
193  /*!
194  * \name Simple implementation of inherited methods.
195  * \{
196  */
197  mbox_id_t
198  id() const override
199  {
200  return underlying_mbox().id();
201  }
202 
203  void
205  const std::type_index & msg_type,
206  ::so_5::abstract_message_sink_t & subscriber ) override
207  {
208  underlying_mbox().subscribe_event_handler( msg_type, subscriber );
209  }
210 
211  void
213  const std::type_index & msg_type,
214  ::so_5::abstract_message_sink_t & subscriber ) noexcept override
215  {
216  underlying_mbox().unsubscribe_event_handler( msg_type, subscriber );
217  }
218 
219  std::string
220  query_name() const override
221  {
222  return underlying_mbox().query_name();
223  }
224 
226  type() const override
227  {
228  return underlying_mbox().type();
229  }
230 
231  void
233  ::so_5::message_delivery_mode_t delivery_mode,
234  const std::type_index & msg_type,
235  const ::so_5::message_ref_t & message,
236  unsigned int redirection_deep ) override
237  {
238  underlying_mbox().do_deliver_message(
239  delivery_mode,
240  msg_type,
241  message,
242  redirection_deep );
243  }
244 
245  void
247  const std::type_index & msg_type,
248  const ::so_5::delivery_filter_t & filter,
249  ::so_5::abstract_message_sink_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::abstract_message_sink_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  * \}
274  */
275  };
276 
277 } /* namespace proxy */
278 
279 } /* namespace mboxes */
280 
281 } /* namespace extra */
282 
283 } /* namespace so_5 */
void drop_delivery_filter(const std::type_index &msg_type, ::so_5::abstract_message_sink_t &subscriber) noexcept override
Definition: proxy.hpp:258
::so_5::abstract_message_box_t & underlying_mbox() const noexcept
An accessor to actual mbox.
Definition: proxy.hpp:178
so_5::environment_t & environment() const noexcept override
Definition: proxy.hpp:268
mbox_type_t type() const override
Definition: proxy.hpp:226
void subscribe_event_handler(const std::type_index &msg_type, ::so_5::abstract_message_sink_t &subscriber) override
Definition: proxy.hpp:204
Ranges for error codes of each submodules.
Definition: details.hpp:13
mbox_id_t id() const override
Definition: proxy.hpp:198
::so_5::mbox_t ensure_underlying_mbox_not_null(::so_5::mbox_t mbox)
Ensure that underlying mbox is not nullptr.
Definition: proxy.hpp:144
void set_delivery_filter(const std::type_index &msg_type, const ::so_5::delivery_filter_t &filter, ::so_5::abstract_message_sink_t &subscriber) override
Definition: proxy.hpp:246
std::string query_name() const override
Definition: proxy.hpp:220
A simple proxy that delegates all calls to underlying actual mbox.
Definition: proxy.hpp:131
const int rc_nullptr_as_underlying_mbox
Null pointer to underlying mbox.
Definition: proxy.hpp:34
const ::so_5::mbox_t m_underlying_mbox
Actual underlying mbox to be used for all calls.
Definition: proxy.hpp:137
simple_t(::so_5::mbox_t underlying_mbox)
Initializing constructor.
Definition: proxy.hpp:185
void unsubscribe_event_handler(const std::type_index &msg_type, ::so_5::abstract_message_sink_t &subscriber) noexcept override
Definition: proxy.hpp:212
void do_deliver_message(::so_5::message_delivery_mode_t delivery_mode, const std::type_index &msg_type, const ::so_5::message_ref_t &message, unsigned int redirection_deep) override
Definition: proxy.hpp:232