SObjectizer 5.8
Loading...
Searching...
No Matches
wrapped_env.cpp
Go to the documentation of this file.
1/*
2 * SObjectizer-5
3 */
4
5/*!
6 * \since
7 * v.5.5.9
8 *
9 * \file
10 * \brief Class wrapped_env and its details.
11 */
12
13#include <so_5/wrapped_env.hpp>
14
15#include <so_5/details/invoke_noexcept_code.hpp>
16
17#include <condition_variable>
18#include <exception>
19#include <mutex>
20#include <thread>
21
22namespace so_5 {
23
24using wrapped_env_details::init_style_t;
25
26namespace
27{
28
29/*!
30 * \since
31 * v.5.5.9
32 *
33 * \brief Implementation of environment to be used inside wrapped_env.
34 */
36 {
37 public:
38 //! Initializing constructor.
40 //! Initialization routine.
41 so_5::generic_simple_init_t init,
42 //! SObjectizer Environment parameters.
43 environment_params_t && env_params,
44 //! How initialization is performed.
45 init_style_t init_style )
46 : environment_t( std::move( env_params ) )
47 , m_init( std::move(init) )
48 , m_init_style{ init_style }
49 {}
50
51 void
52 init() override
53 {
54 // Don't expect that this code throws, but if it does
55 // we can't complete our work correctly, so it's better
56 // to crash the application.
58 {
59 std::lock_guard< std::mutex > lock{ m_status_lock };
61 m_status_cond.notify_all();
62 }
63
64 switch( m_init_style )
65 {
68 break;
69
72 break;
73 }
74
75 // If an exception was caught then the whole
76 // environment has to be stopped after changing
77 // the status.
78 bool should_stop = false;
79
80 {
81 std::lock_guard< std::mutex > lock{ m_status_lock };
82
83 // If exception was caught then we have to stop
84 // the environment.
85 should_stop = static_cast<bool>( m_exception_from_init_functor );
86
88 m_status_cond.notify_all();
89 }
90
91 if( should_stop )
92 {
93 // The environment has to be stopped because
94 // of an exception.
95 this->stop();
96 }
97 } );
98 }
99
100 /*!
101 * @brief Wait for change of the status.
102 *
103 * This method blocks the caller thread while m_status is
104 * status_t::not_started.
105 *
106 * Since v.5.8.2 this method throws if:
107 *
108 * - init_style_t::sync is used;
109 * - an exception is throw from init-functor.
110 *
111 * In that case an exception is caught and then rethrown from
112 * ensure_started() method.
113 */
114 void
116 {
117 /*!
118 * \note This method is necessary because stop() can be
119 * called before run(). In that case there will be an
120 * infinite waiting on join() in wrapped_env_t.
121 */
122 std::unique_lock< std::mutex > lock{ m_status_lock };
124 {
125 m_status_cond.wait( lock,
126 [this]{ return status_t::not_started != m_status; } );
127 }
128
129 // If sync mode is used that we have to wait while
130 // m_status becomes init_functor_completed.
132 {
134 {
135 m_status_cond.wait( lock, [this]{
137 } );
138 }
139
140 // If exception was thrown from init-functor then it
141 // has to be rethrown now.
143 {
144 std::rethrow_exception(
145 std::move( m_exception_from_init_functor ) );
146 }
147 }
148 }
149
150 private:
151 //! Initialization routine.
152 so_5::generic_simple_init_t m_init;
153
154 //! Style of initialization (asynchronous or synchronous).
155 /*!
156 * \since v.5.8.2
157 */
159
160 //! Status of environment.
161 enum class status_t
162 {
163 //! init() is not called yet.
165 //! init() is called and is about to call init-functor.
166 started,
167 //! init-functor completed its work.
169 };
170
171 //! Status of environment.
173
174 //! Lock object for defending status.
175 std::mutex m_status_lock;
176 //! Condition for waiting on status.
177 std::condition_variable m_status_cond;
178
179 /*!
180 * \brief Exception from init-functor.
181 *
182 * In sync mode an exception throw from init-functor has to be
183 * rethrown in ensure_started() method. To do this it's necessary
184 * to store an instance of that exception. This member is
185 * intended to hold an exception caught from init-functor.
186 *
187 * If this member is empty after completion of the
188 * call_init_functor_sync_style() then it's assumed an exception
189 * wasn't thrown.
190 *
191 * \since v.5.8.2
192 */
194
195 /*!
196 * \brief Helper for calling init-functor in asynchronous mode.
197 *
198 * Doesn't handle exceptions.
199 *
200 * \since v.5.8.2
201 */
202 void
204 {
205 m_init( *this );
206 }
207
208 /*!
209 * \brief Helper for calling init-functor in synchronous mode.
210 *
211 * Catches an exception if it's thrown from init-functor.
212 *
213 * \since v.5.8.2
214 */
215 void
217 {
218 try
219 {
220 m_init( *this );
221 }
222 catch( ... )
223 {
224 // Assume that these actions won't throw.
225 std::lock_guard< std::mutex > lock{ m_status_lock };
226 m_exception_from_init_functor = std::current_exception();
227 }
228 }
229 };
230
231} /* namespace anonymous */
232
233/*!
234 * \since
235 * v.5.5.9
236 *
237 * \brief Implementation details for wrapped_env.
238 */
240 {
241 //! Actual environment object.
243
244 //! Helper thread for calling run method.
245 std::thread m_env_thread;
246
247 //! Initializing constructor.
249 so_5::generic_simple_init_t init_func,
250 environment_params_t && params,
251 init_style_t init_style )
252 : m_env{ std::move( init_func ), std::move( params ), init_style }
253 {}
254
256 {
257 // Since v.5.8.2 it may be necessary to call join() in the destructor
258 // in the case when init_style_t::sync is used and an exception
259 // is thrown from init-functor.
260 join();
261 }
262
263 void
265 {
266 m_env_thread = std::thread{ [this]{ m_env.run(); } };
267
268 // Since v.5.8.2 this call may block the current thread
269 // until init-functor completes. It also may throw.
271 }
272
273 void
274 stop() noexcept
275 {
277 }
278
279 void
280 join() noexcept
281 {
282 if( m_env_thread.joinable() ) m_env_thread.join();
283 }
284 };
285
286namespace
287{
288
289std::unique_ptr< wrapped_env_t::details_t >
291 so_5::generic_simple_init_t init_func,
292 environment_params_t && params,
293 init_style_t init_style )
294 {
295 return std::unique_ptr< wrapped_env_t::details_t >(
297 std::move( init_func ),
298 std::move( params ),
299 init_style
300 } );
301 }
302
305 {
307 return std::move( params );
308 }
309
311make_params_via_tuner( so_5::generic_simple_so_env_params_tuner_t tuner )
312 {
314 tuner( params );
315 return params;
316 }
317
318} /* namespace anonymous */
319
321 so_5::generic_simple_init_t init_func,
322 environment_params_t && params,
324 : m_impl{
326 std::move( init_func ),
327 make_necessary_tuning( std::move( params ) ),
328 init_style )
329 }
330 {
332 }
333
337
339 so_5::generic_simple_init_t init_func )
341 std::move( init_func ),
343 {}
344
346 so_5::generic_simple_init_t init_func,
347 so_5::generic_simple_so_env_params_tuner_t params_tuner )
349 std::move( init_func ),
350 make_params_via_tuner( std::move( params_tuner ) ) }
351 {}
352
354 so_5::generic_simple_init_t init_func,
355 environment_params_t && params )
357 std::move( init_func ),
358 std::move( params ),
360 {}
361
363 wait_init_completion_t wait_init_completion_indicator,
364 so_5::generic_simple_init_t init_func )
366 wait_init_completion_indicator,
367 std::move( init_func ),
369 {}
370
372 wait_init_completion_t /*wait_init_completion_indicator*/,
373 so_5::generic_simple_init_t init_func,
374 environment_params_t && params )
376 std::move( init_func ),
377 std::move( params ),
379 {}
380
382 wait_init_completion_t wait_init_completion_indicator,
383 so_5::generic_simple_init_t init_func,
384 so_5::generic_simple_so_env_params_tuner_t params_tuner )
386 wait_init_completion_indicator,
387 std::move( init_func ),
388 make_params_via_tuner( std::move( params_tuner ) ) }
389 {}
390
392 environment_params_t && params )
394 []( environment_t & ) {},
395 std::move( params ) }
396 {}
397
402
405 {
406 return m_impl->m_env;
407 }
408
409void
411 {
412 m_impl->stop();
413 }
414
415void
417 {
418 m_impl->join();
419 }
420
421void
423 {
424 stop();
425 join();
426 }
427
428} /* namespace so_5 */
Implementation of environment to be used inside wrapped_env.
const init_style_t m_init_style
Style of initialization (asynchronous or synchronous).
actual_environment_t(so_5::generic_simple_init_t init, environment_params_t &&env_params, init_style_t init_style)
Initializing constructor.
std::exception_ptr m_exception_from_init_functor
Exception from init-functor.
void call_init_functor_sync_style() noexcept
Helper for calling init-functor in synchronous mode.
@ started
init() is called and is about to call init-functor.
std::condition_variable m_status_cond
Condition for waiting on status.
so_5::generic_simple_init_t m_init
Initialization routine.
void call_init_functor_async_style()
Helper for calling init-functor in asynchronous mode.
std::mutex m_status_lock
Lock object for defending status.
Parameters for the SObjectizer Environment initialization.
environment_params_t & disable_autoshutdown()
Do not shutdown SO Environment when it is becomes empty.
environment_params_t()
Constructor.
SObjectizer Environment.
void run()
Run the SObjectizer Run-Time.
environment_t(environment_params_t &&so_environment_params)
void stop() noexcept
Send a shutdown signal to the Run-Time.
A wrapped environment.
void stop()
Send stop signal to environment.
wrapped_env_t(wait_init_completion_t wait_init_completion_indicator, so_5::generic_simple_init_t init_func, environment_params_t &&params)
A constructor for synchronous mode which receives initialization function and already prepared enviro...
void stop_then_join()
Send stop signal and wait for complete finish of environment's work.
wrapped_env_t(so_5::generic_simple_init_t init_func, environment_params_t &&params)
std::unique_ptr< details_t > m_impl
Implementation details.
wrapped_env_t(environment_params_t &&params)
A constructor which receives already prepared environment's params.
wrapped_env_t(so_5::generic_simple_init_t init_func)
A constructor which receives only initialization function.
wrapped_env_t()
Default constructor.
~wrapped_env_t()
Destructor.
wrapped_env_t(wait_init_completion_t wait_init_completion_indicator, so_5::generic_simple_init_t init_func, so_5::generic_simple_so_env_params_tuner_t params_tuner)
A constructor for synchronous mode which receives initialization function and a function for environm...
wrapped_env_t(wait_init_completion_t wait_init_completion_indicator, so_5::generic_simple_init_t init_func)
A constructor for synchronous mode which receives only initialization function.
wrapped_env_t(so_5::generic_simple_init_t init_func, so_5::generic_simple_so_env_params_tuner_t params_tuner)
A constructor which receives initialization function and a function for environment's params tuning.
void join()
Wait for complete finish of environment's work.
environment_t & environment() const
Access to wrapped environment.
wrapped_env_t(so_5::generic_simple_init_t init_func, environment_params_t &&params, wrapped_env_details::init_style_t init_style)
The main initializing constructor.
wait_init_completion_t
Helper type to be used as indicator of synchronous mode.
environment_params_t make_params_via_tuner(so_5::generic_simple_so_env_params_tuner_t tuner)
environment_params_t make_necessary_tuning(environment_params_t &&params)
std::unique_ptr< wrapped_env_t::details_t > make_details_object(so_5::generic_simple_init_t init_func, environment_params_t &&params, init_style_t init_style)
Some reusable and low-level classes/functions which can be used in public header files.
auto invoke_noexcept_code(L lambda) noexcept -> decltype(lambda())
init_style_t
Style of handling init-functor in the constructor of wrapped_env.
Private part of message limit implementation.
Definition agent.cpp:33
Implementation details for wrapped_env.
std::thread m_env_thread
Helper thread for calling run method.
details_t(so_5::generic_simple_init_t init_func, environment_params_t &&params, init_style_t init_style)
Initializing constructor.
actual_environment_t m_env
Actual environment object.