1 /*
2 SObjectizer 5.
3 */
4
5 /*!
6 \file
7 \brief Functions for creating and binding to the active group dispatcher.
8 */
9
10 #pragma once
11
12 #include <so_5/declspec.hpp>
13
14 #include <so_5/disp_binder.hpp>
15 #include <so_5/nonempty_name.hpp>
16
17 #include <so_5/disp/mpsc_queue_traits/pub.hpp>
18
19 #include <so_5/disp/reuse/work_thread_activity_tracking.hpp>
20
21 #include <string>
22 #include <string_view>
23
24 namespace so_5
25 {
26
27 namespace disp
28 {
29
30 namespace active_group
31 {
32
33 /*!
34 * \brief Alias for namespace with traits of event queue.
35 *
36 * \since
37 * v.5.5.10
38 */
39 namespace queue_traits = so_5::disp::mpsc_queue_traits;
40
41 //
42 // disp_params_t
43 //
44 /*!
45 * \brief Parameters for active group dispatcher.
46 *
47 * \since
48 * v.5.5.10
49 */
50 class disp_params_t
51 : public so_5::disp::reuse::work_thread_activity_tracking_flag_mixin_t< disp_params_t >
52 {
53 using activity_tracking_mixin_t = so_5::disp::reuse::
54 work_thread_activity_tracking_flag_mixin_t< disp_params_t >;
55
56 public :
57 //! Default constructor.
58 disp_params_t() = default;
59
60 friend inline void
swap(disp_params_t & a,disp_params_t & b)61 swap( disp_params_t & a, disp_params_t & b ) noexcept
62 {
63 swap(
64 static_cast< activity_tracking_mixin_t & >(a),
65 static_cast< activity_tracking_mixin_t & >(b) );
66 swap( a.m_queue_params, b.m_queue_params );
67 }
68
69 //! Setter for queue parameters.
70 disp_params_t &
set_queue_params(queue_traits::queue_params_t p)71 set_queue_params( queue_traits::queue_params_t p )
72 {
73 m_queue_params = std::move(p);
74 return *this;
75 }
76
77 //! Tuner for queue parameters.
78 /*!
79 * Accepts lambda-function or functional object which tunes
80 * queue parameters.
81 \code
82 so_5::disp::active_group::make_dispatcher( env,
83 "my_active_group_disp",
84 so_5::disp::active_group::disp_params_t{}.tune_queue_params(
85 []( so_5::disp::active_group::queue_traits::queue_params_t & p ) {
86 p.lock_factory( so_5::disp::active_group::queue_traits::simple_lock_factory() );
87 } ) );
88 \endcode
89 */
90 template< typename L >
91 disp_params_t &
tune_queue_params(L tunner)92 tune_queue_params( L tunner )
93 {
94 tunner( m_queue_params );
95 return *this;
96 }
97
98 //! Getter for queue parameters.
99 const queue_traits::queue_params_t &
queue_params() const100 queue_params() const
101 {
102 return m_queue_params;
103 }
104
105 private :
106 //! Queue parameters.
107 queue_traits::queue_params_t m_queue_params;
108 };
109
110 namespace impl {
111
112 class actual_dispatcher_iface_t;
113
114 //
115 // basic_dispatcher_iface_t
116 //
117 /*!
118 * \brief The very basic interface of %active_group dispatcher.
119 *
120 * This class contains a minimum that is necessary for implementation
121 * of dispatcher_handle class.
122 *
123 * \since
124 * v.5.6.0
125 */
126 class basic_dispatcher_iface_t
127 : public std::enable_shared_from_this<actual_dispatcher_iface_t>
128 {
129 public :
130 virtual ~basic_dispatcher_iface_t() noexcept = default;
131
132 [[nodiscard]]
133 virtual disp_binder_shptr_t
134 binder( nonempty_name_t group_name ) = 0;
135 };
136
137 using basic_dispatcher_iface_shptr_t =
138 std::shared_ptr< basic_dispatcher_iface_t >;
139
140 class dispatcher_handle_maker_t;
141
142 } /* namespace impl */
143
144 //
145 // dispatcher_handle_t
146 //
147
148 /*!
149 * \since
150 * v.5.6.0
151 *
152 * \brief A handle for %active_group dispatcher.
153 */
154 class [[nodiscard]] dispatcher_handle_t
155 {
156 friend class impl::dispatcher_handle_maker_t;
157
158 //! A reference to actual implementation of a dispatcher.
159 impl::basic_dispatcher_iface_shptr_t m_dispatcher;
160
dispatcher_handle_t(impl::basic_dispatcher_iface_shptr_t dispatcher)161 dispatcher_handle_t(
162 impl::basic_dispatcher_iface_shptr_t dispatcher ) noexcept
163 : m_dispatcher{ std::move(dispatcher) }
164 {}
165
166 //! Is this handle empty?
167 bool
empty() const168 empty() const noexcept { return !m_dispatcher; }
169
170 public :
171 dispatcher_handle_t() noexcept = default;
172
173 //! Get a binder for that dispatcher.
174 /*!
175 * \attention
176 * An attempt to call this method on empty handle is UB.
177 */
178 [[nodiscard]]
179 disp_binder_shptr_t
binder(nonempty_name_t group_name) const180 binder(
181 //! Name of group for a new agent.
182 nonempty_name_t group_name ) const
183 {
184 return m_dispatcher->binder( std::move(group_name) );
185 }
186
187 //! Is this handle empty?
operator bool() const188 operator bool() const noexcept { return empty(); }
189
190 //! Does this handle contain a reference to dispatcher?
191 bool
operator !() const192 operator!() const noexcept { return !empty(); }
193
194 //! Drop the content of handle.
195 void
reset()196 reset() noexcept { m_dispatcher.reset(); }
197 };
198
199 /*!
200 * \brief Create an instance of %active_group dispatcher.
201 *
202 * \par Usage sample
203 \code
204 auto disp = so_5::disp::active_group::make_dispatcher(
205 env,
206 "request_handler",
207 // Additional params with specific options for queue's traits.
208 so_5::disp::active_group::disp_params_t{}.tune_queue_params(
209 []( so_5::disp::active_group::queue_traits::queue_params_t & p ) {
210 p.lock_factory( so_5::disp::active_obj::queue_traits::simple_lock_factory() );
211 } ) );
212 auto coop = env.make_coop(
213 // The main dispatcher for that coop will be
214 // this instance of active_group dispatcher.
215 disp.binder( "request_handler" ) );
216 \endcode
217 *
218 * \since
219 * v.5.6.0
220 */
221 SO_5_FUNC dispatcher_handle_t
222 make_dispatcher(
223 //! SObjectizer Environment to work in.
224 so_5::environment_t & env,
225 //! Value for creating names of data sources for
226 //! run-time monitoring.
227 const std::string_view data_sources_name_base,
228 //! Parameters for dispatcher.
229 disp_params_t params );
230
231 /*!
232 * \brief Create an instance of %active_group dispatcher.
233 *
234 * \par Usage sample
235 \code
236 auto disp = so_5::disp::active_group::make_dispatcher(
237 env,
238 "long_req_handlers" );
239
240 auto coop = env.make_coop(
241 // The main dispatcher for that coop will be
242 // this instance of active_group dispatcher.
243 disp.binder( "passive_objects" ) );
244 \endcode
245 *
246 * \since
247 * v.5.6.0
248 */
249 inline dispatcher_handle_t
make_dispatcher(so_5::environment_t & env,const std::string_view data_sources_name_base)250 make_dispatcher(
251 //! SObjectizer Environment to work in.
252 so_5::environment_t & env,
253 //! Value for creating names of data sources for
254 //! run-time monitoring.
255 const std::string_view data_sources_name_base )
256 {
257 return make_dispatcher( env, data_sources_name_base, disp_params_t{} );
258 }
259
260 /*!
261 * \brief Create an instance of %active_group dispatcher.
262 *
263 * \par Usage sample
264 \code
265 auto disp = so_5::disp::active_group::make_dispatcher( env );
266
267 auto coop = env.make_coop(
268 // The main dispatcher for that coop will be
269 // this instance of active_group dispatcher.
270 disp.binder( "passive_objects" ) );
271 \endcode
272 *
273 * \since
274 * v.5.6.0
275 */
276 inline dispatcher_handle_t
make_dispatcher(so_5::environment_t & env)277 make_dispatcher(
278 //! SObjectizer Environment to work in.
279 so_5::environment_t & env )
280 {
281 return make_dispatcher( env, std::string_view{} );
282 }
283
284 } /* namespace active_group */
285
286 } /* namespace disp */
287
288 } /* namespace so_5 */
289
290