SObjectizer 5.8
Loading...
Searching...
No Matches
timers.cpp
Go to the documentation of this file.
1/*
2 SObjectizer 5.
3*/
4
5/*!
6 \file
7 \since
8 v.5.5.0
9
10 \brief Timers and tools for working with timers.
11*/
12
13#include <so_5/details/abort_on_fatal_error.hpp>
14
15#include <so_5/impl/mbox_iface_for_timers.hpp>
16
17#include <so_5/timers.hpp>
18
19#include <so_5/3rd_party/timertt/all.hpp>
20
21namespace so_5
22{
23
25{
26
27//
28// actual_timer_t
29//
30/*!
31 * \since
32 * v.5.5.0
33 *
34 * \brief An actual implementation of timer interface.
35 *
36 * \note
37 * Since v.5.5.19 this template can be used with timer_thread and
38 * with timer_manager.
39 *
40 * \tparam Timer A type of timertt-based thread/manager which implements timers.
41 */
42template< class Timer >
43class actual_timer_t : public timer_t
44 {
45 public :
46 //! The actual type of timer holder for timertt.
47 using timer_holder_t = timertt::timer_object_holder<
48 typename Timer::thread_safety >;
49
50 //! Initialized constructor.
52 Timer * thread )
53 : m_thread( thread )
54 , m_timer( thread->allocate() )
55 {}
56 virtual ~actual_timer_t() noexcept override
57 {
59 }
60
61 timer_holder_t &
62 timer_holder() noexcept
63 {
64 return m_timer;
65 }
66
67 virtual bool
68 is_active() const noexcept override
69 {
70 return (m_thread != nullptr);
71 }
72
73 virtual void
74 release() noexcept override
75 {
76 if( m_thread )
77 {
78 m_thread->deactivate( m_timer );
79 m_thread = nullptr;
80 m_timer.reset();
81 }
82 }
83
84 private :
85 //! Timer thread for the timer.
86 /*!
87 * nullptr means that timer is deactivated.
88 */
89 Timer * m_thread;
90
91 //! Underlying timer object reference.
92 timer_holder_t m_timer;
93 };
94
95//
96// timer_action_for_timer_thread_t
97//
98/*!
99 * \brief A functor to be used as timer action in implementation
100 * of timer thread.
101 *
102 * \since
103 * v.5.5.20
104 */
106 {
107 std::type_index m_type_index;
108 mbox_t m_mbox;
109 message_ref_t m_msg;
110
111 public:
113 std::type_index type_index,
114 mbox_t mbox,
115 message_ref_t msg )
116 : m_type_index( std::move(type_index) )
117 , m_mbox( std::move(mbox) )
118 , m_msg( std::move(msg) )
119 {}
120
121 void
127 };
128
129//
130// actual_thread_t
131//
132/*!
133 * \since
134 * v.5.5.0
135 *
136 * \brief An actual implementation of timer thread.
137 *
138 * \tparam Timer_Thread A type of timertt-based thread which implements timers.
139 */
140template< class Timer_Thread >
142 {
143 using timer_demand_t = actual_timer_t< Timer_Thread >;
144
145 public :
146 //! Initializing constructor.
148 //! Real timer thread.
149 std::unique_ptr< Timer_Thread > thread )
150 : m_thread( std::move( thread ) )
151 {}
152
153 virtual void
154 start() override
155 {
156 m_thread->start();
157 }
158
159 virtual void
160 finish() override
161 {
162 m_thread->shutdown_and_join();
163 }
164
165 virtual timer_id_t
167 const std::type_index & type_index,
168 const mbox_t & mbox,
169 const message_ref_t & msg,
170 std::chrono::steady_clock::duration pause,
171 std::chrono::steady_clock::duration period ) override
172 {
173 auto timer = std::make_unique< timer_demand_t >( m_thread.get() );
174
175 m_thread->activate( timer->timer_holder(),
176 pause,
177 period,
178 timer_action_for_timer_thread_t( type_index, mbox, msg ) );
179
180 return timer_id_t( timer.release() );
181 }
182
183 virtual void
185 const std::type_index & type_index,
186 const mbox_t & mbox,
187 const message_ref_t & msg,
188 std::chrono::steady_clock::duration pause,
189 std::chrono::steady_clock::duration period ) override
190 {
191 m_thread->activate(
192 pause,
193 period,
194 timer_action_for_timer_thread_t( type_index, mbox, msg ) );
195 }
196
198 query_stats() override
199 {
200 auto d = m_thread->get_timer_quantities();
201
203 d.m_single_shot_count,
204 d.m_periodic_count
205 };
206 }
207
208 private :
209 std::unique_ptr< Timer_Thread > m_thread;
210 };
211
212//
213// timer_action_for_timer_manager_t
214//
215/*!
216 * \brief A functor to be used as timer action in implementation
217 * of timer thread.
218 *
219 * \since
220 * v.5.5.20
221 */
223 {
226 std::type_index m_type_index;
227 mbox_t m_mbox;
228 message_ref_t m_msg;
229
230 public:
233 collector,
234 std::type_index type_index,
235 mbox_t mbox,
236 message_ref_t msg )
237 : m_collector( collector )
238 , m_type_index( std::move(type_index) )
239 , m_mbox( std::move(mbox) )
240 , m_msg( std::move(msg) )
241 {}
242
243 void
248 };
249
250//
251// actual_manager_t
252//
253/*!
254 * \brief An actual implementation of timer_manager.
255 *
256 * \tparam Timer_Manager A type of timertt-based manager which implements timers.
257 *
258 * \since
259 * v.5.5.19
260 */
261template< class Timer_Manager >
263 {
264 using timer_demand_t = actual_timer_t< Timer_Manager >;
265
266 public :
267 //! Initializing constructor.
269 //! Real timer thread.
270 std::unique_ptr< Timer_Manager > manager,
271 //! Collector for elapsed timers.
273 collector )
274 : m_manager( std::move( manager ) )
275 , m_collector( std::move( collector ) )
276 {}
277
278 virtual void
280 {
281 m_manager->process_expired_timers();
282 }
283
284 virtual std::chrono::steady_clock::duration
286 std::chrono::steady_clock::duration default_timer ) override
287 {
288 return m_manager->timeout_before_nearest_timer( default_timer );
289 }
290
291 virtual timer_id_t
293 const std::type_index & type_index,
294 const mbox_t & mbox,
295 const message_ref_t & msg,
296 std::chrono::steady_clock::duration pause,
297 std::chrono::steady_clock::duration period ) override
298 {
299 auto timer = std::make_unique< timer_demand_t >( m_manager.get() );
300
301 m_manager->activate( timer->timer_holder(),
302 pause,
303 period,
305 m_collector, type_index, mbox, msg ) );
306
307 return timer_id_t( timer.release() );
308 }
309
310 virtual void
312 const std::type_index & type_index,
313 const mbox_t & mbox,
314 const message_ref_t & msg,
315 std::chrono::steady_clock::duration pause,
316 std::chrono::steady_clock::duration period ) override
317 {
318 m_manager->activate(
319 pause,
320 period,
322 m_collector, type_index, mbox, msg ) );
323 }
324
325 virtual bool
326 empty() override
327 {
328 return m_manager->empty();
329 }
330
332 query_stats() override
333 {
334 auto d = m_manager->get_timer_quantities();
335
337 d.m_single_shot_count,
338 d.m_periodic_count
339 };
340 }
341
342 private :
343 std::unique_ptr< Timer_Manager > m_manager;
346 };
347
348//
349// error_logger_for_timertt_t
350//
351/*!
352 * \since
353 * v.5.5.0
354 *
355 * \brief Type of error_logger for timertt stuff.
356 */
357using error_logger_for_timertt_t = std::function< void(const std::string &) >;
358
359//
360// create_error_logger_for_timertt
361//
362
363#if defined(__clang__)
364#pragma clang diagnostic push
365#pragma clang diagnostic ignored "-Wmissing-prototypes"
366#endif
367
368error_logger_for_timertt_t
369create_error_logger_for_timertt( const error_logger_shptr_t & logger )
370 {
371 // NOTE: if this logger throws then timertt will catch the exception
372 // and terminate the application.
373 // It's normal because timertt calls this logger right before calling
374 // std::abort() in the cases when timertt can't recover from
375 // previous failures.
376 return [logger]( const std::string & msg ) {
377 SO_5_LOG_ERROR( *logger, stream ) {
378 stream << "error inside timer_thread: " << msg;
379 }
380 };
381 }
382
383#if defined(__clang__)
384#pragma clang diagnostic pop
385#endif
386
387//
388// exception_handler_for_timertt_t
389//
390/*!
391 * \since
392 * v.5.5.0
393 *
394 * \brief Type of actor_exception_handler for timertt stuff.
395 */
396using exception_handler_for_timertt_t =
397 std::function< void(const std::exception &) >;
398
399//
400// create_exception_handler_for_timertt
401//
402
403#if defined(__clang__)
404#pragma clang diagnostic push
405#pragma clang diagnostic ignored "-Wmissing-prototypes"
406#endif
407
408exception_handler_for_timertt_t
410 const error_logger_shptr_t & logger )
411 {
412 return [logger]( const std::exception & x ) {
414 SO_5_LOG_ERROR( *logger, stream ) {
415 stream << "exception has been thrown and caught inside "
416 "timer_thread, application will be aborted. "
417 "Exception: " << x.what();
418 }
419 } );
420 };
421 }
422
423exception_handler_for_timertt_t
425 const error_logger_shptr_t & logger )
426 {
427 return [logger]( const std::exception & x ) {
429 SO_5_LOG_ERROR( *logger, stream ) {
430 stream << "exception has been thrown and caught inside "
431 "timer_manager, application will be aborted. "
432 "Exception: " << x.what();
433 }
434 } );
435 };
436 }
437
438#if defined(__clang__)
439#pragma clang diagnostic pop
440#endif
441
442/*!
443 * \name Short synonyms for timertt templates.
444 * \{
445 */
446//! timer_wheel thread type.
447using timer_wheel_thread_t = timertt::timer_wheel_thread_template<
449 error_logger_for_timertt_t,
450 exception_handler_for_timertt_t >;
451
452//! timer_heap thread type.
453using timer_heap_thread_t = timertt::timer_heap_thread_template<
455 error_logger_for_timertt_t,
456 exception_handler_for_timertt_t >;
457
458//! timer_list thread type.
459using timer_list_thread_t = timertt::timer_list_thread_template<
461 error_logger_for_timertt_t,
462 exception_handler_for_timertt_t >;
463
464//! timer_wheel manager type.
465using timer_wheel_manager_t = timertt::timer_wheel_manager_template<
468 error_logger_for_timertt_t,
469 exception_handler_for_timertt_t >;
470
471//! timer_heap manager type.
472using timer_heap_manager_t = timertt::timer_heap_manager_template<
475 error_logger_for_timertt_t,
476 exception_handler_for_timertt_t >;
477
478//! timer_list manager type.
479using timer_list_manager_t = timertt::timer_list_manager_template<
482 error_logger_for_timertt_t,
483 exception_handler_for_timertt_t >;
484/*!
485 * \}
486 */
487
488} /* namespace timers_details */
489
490SO_5_FUNC timer_thread_unique_ptr_t
492 error_logger_shptr_t logger )
493 {
494 using timertt_thread_t = timers_details::timer_wheel_thread_t;
495
497 std::move(logger),
498 timertt_thread_t::default_wheel_size(),
499 timertt_thread_t::default_granularity() );
500 }
501
502SO_5_FUNC timer_thread_unique_ptr_t
504 error_logger_shptr_t logger,
505 unsigned int wheel_size,
506 std::chrono::steady_clock::duration granuality )
507 {
508 using timertt_thread_t = timers_details::timer_wheel_thread_t;
509 using namespace timers_details;
510
511 std::unique_ptr< timertt_thread_t > thread(
512 new timertt_thread_t(
513 wheel_size,
514 granuality,
517
518 return timer_thread_unique_ptr_t(
519 new actual_thread_t< timertt_thread_t >( std::move( thread ) ) );
520 }
521
522SO_5_FUNC timer_thread_unique_ptr_t
524 error_logger_shptr_t logger )
525 {
526 using timertt_thread_t = timers_details::timer_heap_thread_t;
527
529 std::move(logger),
530 timertt_thread_t::default_initial_heap_capacity() );
531 }
532
533SO_5_FUNC timer_thread_unique_ptr_t
535 error_logger_shptr_t logger,
536 std::size_t initial_heap_capacity )
537 {
538 using timertt_thread_t = timers_details::timer_heap_thread_t;
539 using namespace timers_details;
540
541 std::unique_ptr< timertt_thread_t > thread(
542 new timertt_thread_t(
543 initial_heap_capacity,
546
547 return timer_thread_unique_ptr_t(
548 new actual_thread_t< timertt_thread_t >( std::move( thread ) ) );
549 }
550
551SO_5_FUNC timer_thread_unique_ptr_t
553 error_logger_shptr_t logger )
554 {
555 using timertt_thread_t = timers_details::timer_list_thread_t;
556 using namespace timers_details;
557
558 std::unique_ptr< timertt_thread_t > thread(
559 new timertt_thread_t(
562
563 return timer_thread_unique_ptr_t(
564 new actual_thread_t< timertt_thread_t >( std::move( thread ) ) );
565 }
566
567SO_5_FUNC timer_manager_unique_ptr_t
569 error_logger_shptr_t logger,
572 {
573 using timertt_manager_t = timers_details::timer_wheel_manager_t;
574
576 std::move(logger),
577 collector,
578 timertt_manager_t::default_wheel_size(),
579 timertt_manager_t::default_granularity() );
580 }
581
582SO_5_FUNC timer_manager_unique_ptr_t
584 error_logger_shptr_t logger,
587 unsigned int wheel_size,
588 std::chrono::steady_clock::duration granuality )
589 {
590 using timertt_manager_t = timers_details::timer_wheel_manager_t;
591 using namespace timers_details;
592
593 auto manager = std::make_unique< timertt_manager_t >(
594 wheel_size,
595 granuality,
598
599 return std::make_unique< actual_manager_t< timertt_manager_t > >(
600 std::move( manager ),
601 collector );
602 }
603
604SO_5_FUNC timer_manager_unique_ptr_t
606 error_logger_shptr_t logger,
609 {
610 using timertt_manager_t = timers_details::timer_heap_manager_t;
611
613 std::move(logger),
614 collector,
615 timertt_manager_t::default_initial_heap_capacity() );
616 }
617
618SO_5_FUNC timer_manager_unique_ptr_t
620 error_logger_shptr_t logger,
623 std::size_t initial_heap_capacity )
624 {
625 using timertt_manager_t = timers_details::timer_heap_manager_t;
626 using namespace timers_details;
627
628 auto manager = std::make_unique< timertt_manager_t >(
629 initial_heap_capacity,
632
633 return std::make_unique< actual_manager_t< timertt_manager_t > >(
634 std::move( manager ),
635 collector );
636 }
637
638SO_5_FUNC timer_manager_unique_ptr_t
640 error_logger_shptr_t logger,
643 {
644 using timertt_manager_t = timers_details::timer_list_manager_t;
645 using namespace timers_details;
646
647 auto manager = std::make_unique< timertt_manager_t >(
650
651 return std::make_unique< actual_manager_t< timertt_manager_t > >(
652 std::move( manager ),
653 collector );
654 }
655
656} /* namespace so_5 */
Helper class for accessing protected members from mbox interface.
void deliver_message_from_timer(const std::type_index &msg_type, const message_ref_t &message)
intrusive_ptr_t(intrusive_ptr_t &&o) noexcept
Move constructor.
Helper class for indication of long-lived reference via its type.
Definition outliving.hpp:98
T & get() const noexcept
outliving_reference_t(outliving_reference_t const &o) noexcept
An indentificator for the timer.
Definition timers.hpp:73
An interface for collector of elapsed timers.
Definition timers.hpp:436
virtual void accept(std::type_index type_index, mbox_t mbox, message_ref_t msg)=0
Accept and store info about elapsed timer.
Timer manager interface.
Definition timers.hpp:409
A base class for timer identificator.
Definition timers.hpp:48
Timer thread interface.
Definition timers.hpp:146
An actual implementation of timer_manager.
Definition timers.cpp:263
virtual timer_thread_stats_t query_stats() override
Get statistics for run-time monitoring.
Definition timers.cpp:332
virtual void schedule_anonymous(const std::type_index &type_index, const mbox_t &mbox, const message_ref_t &msg, std::chrono::steady_clock::duration pause, std::chrono::steady_clock::duration period) override
Push anonymous delayed/periodic message to the timer queue.
Definition timers.cpp:311
actual_manager_t(std::unique_ptr< Timer_Manager > manager, outliving_reference_t< timer_manager_t::elapsed_timers_collector_t > collector)
Initializing constructor.
Definition timers.cpp:268
outliving_reference_t< timer_manager_t::elapsed_timers_collector_t > m_collector
Definition timers.cpp:345
virtual bool empty() override
Definition timers.cpp:326
virtual void process_expired_timers() override
Translation of expired timers into message sends.
Definition timers.cpp:279
virtual timer_id_t schedule(const std::type_index &type_index, const mbox_t &mbox, const message_ref_t &msg, std::chrono::steady_clock::duration pause, std::chrono::steady_clock::duration period) override
Push delayed/periodic message to the timer queue.
Definition timers.cpp:292
std::unique_ptr< Timer_Manager > m_manager
Definition timers.cpp:343
virtual std::chrono::steady_clock::duration timeout_before_nearest_timer(std::chrono::steady_clock::duration default_timer) override
Calculate time before the nearest timer (if any).
Definition timers.cpp:285
An actual implementation of timer thread.
Definition timers.cpp:142
std::unique_ptr< Timer_Thread > m_thread
Definition timers.cpp:209
virtual timer_thread_stats_t query_stats() override
Get statistics for run-time monitoring.
Definition timers.cpp:198
virtual void start() override
Launch timer.
Definition timers.cpp:154
actual_thread_t(std::unique_ptr< Timer_Thread > thread)
Initializing constructor.
Definition timers.cpp:147
virtual void finish() override
Finish timer and wait for full stop.
Definition timers.cpp:160
virtual timer_id_t schedule(const std::type_index &type_index, const mbox_t &mbox, const message_ref_t &msg, std::chrono::steady_clock::duration pause, std::chrono::steady_clock::duration period) override
Push delayed/periodic message to the timer queue.
Definition timers.cpp:166
virtual void schedule_anonymous(const std::type_index &type_index, const mbox_t &mbox, const message_ref_t &msg, std::chrono::steady_clock::duration pause, std::chrono::steady_clock::duration period) override
Push anonymous delayed/periodic message to the timer queue.
Definition timers.cpp:184
An actual implementation of timer interface.
Definition timers.cpp:44
timer_holder_t & timer_holder() noexcept
Definition timers.cpp:62
actual_timer_t(Timer *thread)
Initialized constructor.
Definition timers.cpp:51
virtual void release() noexcept override
Release the timer event.
Definition timers.cpp:74
timer_holder_t m_timer
Underlying timer object reference.
Definition timers.cpp:92
virtual ~actual_timer_t() noexcept override
Definition timers.cpp:56
virtual bool is_active() const noexcept override
Is this timer event is active?
Definition timers.cpp:68
Timer * m_thread
Timer thread for the timer.
Definition timers.cpp:89
A functor to be used as timer action in implementation of timer thread.
Definition timers.cpp:223
timer_action_for_timer_manager_t(outliving_reference_t< timer_manager_t::elapsed_timers_collector_t > collector, std::type_index type_index, mbox_t mbox, message_ref_t msg)
Definition timers.cpp:231
outliving_reference_t< timer_manager_t::elapsed_timers_collector_t > m_collector
Definition timers.cpp:225
A functor to be used as timer action in implementation of timer thread.
Definition timers.cpp:106
timer_action_for_timer_thread_t(std::type_index type_index, mbox_t mbox, message_ref_t msg)
Definition timers.cpp:112
timer_heap_thread_template(std::size_t initial_heap_capacity, Error_Logger error_logger, Actor_Exception_Handler exception_handler)
Constructor with all parameters.
timer_list_thread_template(Error_Logger error_logger, Actor_Exception_Handler actor_exception_handler)
Constructor with all parameters.
An intrusive smart pointer to timer demand.
timer_wheel_thread_template(unsigned int wheel_size, monotonic_clock::duration granularity, Error_Logger error_logger, Actor_Exception_Handler exception_handler)
Constructor with all parameters.
#define SO_5_FUNC
Definition declspec.hpp:48
#define SO_5_LOG_ERROR(logger, var_name)
A special macro for helping error logging.
Some reusable and low-level classes/functions which can be used in public header files.
void abort_on_fatal_error(L logging_lambda) noexcept
Details of SObjectizer run-time implementations.
Definition agent.cpp:780
Timers implementation details.
Definition timers.cpp:25
exception_handler_for_timertt_t create_exception_handler_for_timertt_thread(const error_logger_shptr_t &logger)
Definition timers.cpp:409
exception_handler_for_timertt_t create_exception_handler_for_timertt_manager(const error_logger_shptr_t &logger)
Definition timers.cpp:424
error_logger_for_timertt_t create_error_logger_for_timertt(const error_logger_shptr_t &logger)
Definition timers.cpp:369
Private part of message limit implementation.
Definition agent.cpp:33
SO_5_FUNC timer_manager_unique_ptr_t create_timer_heap_manager(error_logger_shptr_t logger, outliving_reference_t< timer_manager_t::elapsed_timers_collector_t > collector, std::size_t initial_heap_capacity)
Create timer manager based on timer_heap mechanism.
Definition timers.cpp:619
SO_5_FUNC timer_thread_unique_ptr_t create_timer_wheel_thread(error_logger_shptr_t logger)
Create timer thread based on timer_wheel mechanism.
Definition timers.cpp:491
SO_5_FUNC timer_thread_unique_ptr_t create_timer_heap_thread(error_logger_shptr_t logger, std::size_t initial_heap_capacity)
Create timer thread based on timer_heap mechanism.
Definition timers.cpp:534
SO_5_FUNC timer_thread_unique_ptr_t create_timer_list_thread(error_logger_shptr_t logger)
Create timer thread based on timer_list mechanism.
Definition timers.cpp:552
SO_5_FUNC timer_manager_unique_ptr_t create_timer_list_manager(error_logger_shptr_t logger, outliving_reference_t< timer_manager_t::elapsed_timers_collector_t > collector)
Create timer thread based on timer_list mechanism.
Definition timers.cpp:639
SO_5_FUNC timer_manager_unique_ptr_t create_timer_wheel_manager(error_logger_shptr_t logger, outliving_reference_t< timer_manager_t::elapsed_timers_collector_t > collector)
Create timer manager based on timer_wheel mechanism.
Definition timers.cpp:568
SO_5_FUNC timer_manager_unique_ptr_t create_timer_wheel_manager(error_logger_shptr_t logger, outliving_reference_t< timer_manager_t::elapsed_timers_collector_t > collector, unsigned int wheel_size, std::chrono::steady_clock::duration granuality)
Create timer manager based on timer_wheel mechanism.
Definition timers.cpp:583
SO_5_FUNC timer_manager_unique_ptr_t create_timer_heap_manager(error_logger_shptr_t logger, outliving_reference_t< timer_manager_t::elapsed_timers_collector_t > collector)
Create timer manager based on timer_heap mechanism.
Definition timers.cpp:605
SO_5_FUNC timer_thread_unique_ptr_t create_timer_wheel_thread(error_logger_shptr_t logger, unsigned int wheel_size, std::chrono::steady_clock::duration granuality)
Create timer thread based on timer_wheel mechanism.
Definition timers.cpp:503
SO_5_FUNC timer_thread_unique_ptr_t create_timer_heap_thread(error_logger_shptr_t logger)
Create timer thread based on timer_heap mechanism.
Definition timers.cpp:523
Top-level project's namespace.
Statistics for run-time monitoring.
Definition timers.hpp:120
static std::size_t default_initial_heap_capacity()
Default initial capacity of heap-array.
static unsigned int default_wheel_size()
Default wheel size.
static monotonic_clock::duration default_granularity()
Default tick duration.
Indicator for not-thread-safe implementation.
Container for thread safety flags.