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