timer.hpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /*
  2. * Copyright (c) 2017-2023 zhllxt
  3. *
  4. * author : zhllxt
  5. * email : 37792738@qq.com
  6. *
  7. * Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. */
  10. #ifndef __ASIO2_TIMER_HPP__
  11. #define __ASIO2_TIMER_HPP__
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. #pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <asio2/base/detail/push_options.hpp>
  16. #include <cstdint>
  17. #include <memory>
  18. #include <chrono>
  19. #include <atomic>
  20. #include <string>
  21. #include <string_view>
  22. #include <asio2/base/iopool.hpp>
  23. #include <asio2/base/log.hpp>
  24. #include <asio2/base/define.hpp>
  25. #include <asio2/base/detail/object.hpp>
  26. #include <asio2/base/detail/allocator.hpp>
  27. #include <asio2/base/detail/util.hpp>
  28. #include <asio2/base/impl/thread_id_cp.hpp>
  29. #include <asio2/base/impl/user_timer_cp.hpp>
  30. #include <asio2/base/impl/post_cp.hpp>
  31. #include <asio2/base/impl/condition_event_cp.hpp>
  32. namespace asio2::detail
  33. {
  34. struct template_args_timer
  35. {
  36. static constexpr std::size_t allocator_storage_size = 256;
  37. };
  38. ASIO2_CLASS_FORWARD_DECLARE_BASE;
  39. template<class derived_t, class args_t = template_args_timer>
  40. class timer_impl_t
  41. : public object_t <derived_t >
  42. , public iopool_cp <derived_t, args_t>
  43. , public thread_id_cp <derived_t, args_t>
  44. , public user_timer_cp <derived_t, args_t>
  45. , public post_cp <derived_t, args_t>
  46. , public condition_event_cp<derived_t, args_t>
  47. {
  48. ASIO2_CLASS_FRIEND_DECLARE_BASE;
  49. public:
  50. using super = object_t <derived_t >;
  51. using self = timer_impl_t<derived_t, args_t>;
  52. using iopoolcp = iopool_cp<derived_t, args_t>;
  53. using args_type = args_t;
  54. /**
  55. * @brief constructor
  56. */
  57. explicit timer_impl_t()
  58. : super()
  59. , iopool_cp <derived_t, args_t>(1)
  60. , user_timer_cp <derived_t, args_t>()
  61. , post_cp <derived_t, args_t>()
  62. , condition_event_cp<derived_t, args_t>()
  63. , io_ (iopoolcp::_get_io(0))
  64. {
  65. this->start();
  66. }
  67. template<class Scheduler, std::enable_if_t<!std::is_integral_v<detail::remove_cvref_t<Scheduler>>, int> = 0>
  68. explicit timer_impl_t(Scheduler&& scheduler)
  69. : super()
  70. , iopool_cp <derived_t, args_t>(std::forward<Scheduler>(scheduler))
  71. , user_timer_cp <derived_t, args_t>()
  72. , post_cp <derived_t, args_t>()
  73. , condition_event_cp<derived_t, args_t>()
  74. , io_ (iopoolcp::_get_io(0))
  75. {
  76. #if defined(ASIO2_ENABLE_LOG)
  77. #if defined(ASIO2_ALLOCATOR_STORAGE_SIZE)
  78. static_assert(decltype(wallocator_)::storage_size == ASIO2_ALLOCATOR_STORAGE_SIZE);
  79. #else
  80. static_assert(decltype(wallocator_)::storage_size == args_t::allocator_storage_size);
  81. #endif
  82. #endif
  83. this->start();
  84. }
  85. /**
  86. * @brief destructor
  87. */
  88. ~timer_impl_t()
  89. {
  90. this->stop();
  91. }
  92. /**
  93. * @brief start
  94. */
  95. inline bool start()
  96. {
  97. derived_t& derive = this->derived();
  98. // if log is enabled, init the log first, otherwise when "Too many open files" error occurs,
  99. // the log file will be created failed too.
  100. #if defined(ASIO2_ENABLE_LOG)
  101. asio2::detail::get_logger();
  102. #endif
  103. bool ret = this->start_iopool(); // start the io_context pool
  104. if (ret)
  105. {
  106. derive.io_->regobj(&derive);
  107. derive.dispatch([&derive]() mutable
  108. {
  109. // init the running thread id
  110. derive.io_->init_thread_id();
  111. });
  112. }
  113. return ret;
  114. }
  115. /**
  116. * @brief stop
  117. */
  118. inline void stop()
  119. {
  120. if (this->is_iopool_stopped())
  121. return;
  122. derived_t& derive = this->derived();
  123. derive.io_->unregobj(&derive);
  124. // close user custom timers
  125. this->stop_all_timers();
  126. // close all posted timed tasks
  127. this->stop_all_timed_tasks();
  128. // close all async_events
  129. this->notify_all_condition_events();
  130. // stop the io_context pool
  131. this->stop_iopool();
  132. }
  133. /**
  134. * @brief destroy the content of all member variables, this is used for solve the memory leaks.
  135. * After this function is called, this class object cannot be used again.
  136. */
  137. inline void destroy()
  138. {
  139. derived_t& derive = this->derived();
  140. derive.io_.reset();
  141. derive.destroy_iopool();
  142. }
  143. public:
  144. /**
  145. * @brief get the io object reference
  146. */
  147. inline io_t & io() noexcept { return *(this->io_); }
  148. /**
  149. * @brief get the io object reference
  150. */
  151. inline io_t const& io() const noexcept { return *(this->io_); }
  152. protected:
  153. /**
  154. * @brief get the recv/read allocator object reference
  155. */
  156. inline auto & rallocator() noexcept { return this->wallocator_; }
  157. /**
  158. * @brief get the send/write allocator object reference
  159. */
  160. inline auto & wallocator() noexcept { return this->wallocator_; }
  161. protected:
  162. /// The io_context wrapper used to handle the accept event.
  163. std::shared_ptr<io_t> io_;
  164. /// The memory to use for handler-based custom memory allocation. used fo send/write.
  165. handler_memory<std::false_type, assizer<args_t>> wallocator_;
  166. };
  167. }
  168. namespace asio2
  169. {
  170. class timer : public detail::timer_impl_t<timer, detail::template_args_timer>
  171. {
  172. public:
  173. using detail::timer_impl_t<timer, detail::template_args_timer>::timer_impl_t;
  174. };
  175. }
  176. #include <asio2/base/detail/pop_options.hpp>
  177. #endif // !__ASIO2_TIMER_HPP__