listener.hpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  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. * C++0x : Storing any type of std::function in a std::map
  11. * https://stackoverflow.com/questions/7624017/c0x-storing-any-type-of-stdfunction-in-a-stdmap
  12. */
  13. #ifndef __ASIO2_LISTENER_HPP__
  14. #define __ASIO2_LISTENER_HPP__
  15. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  16. #pragma once
  17. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  18. #include <memory>
  19. #include <functional>
  20. #include <array>
  21. #include <tuple>
  22. #include <type_traits>
  23. #include <asio2/base/error.hpp>
  24. #include <asio2/base/log.hpp>
  25. #include <asio2/base/detail/util.hpp>
  26. namespace asio2::detail
  27. {
  28. enum class event_type : std::int8_t
  29. {
  30. recv,
  31. send,
  32. connect,
  33. disconnect,
  34. accept,
  35. handshake,
  36. upgrade,
  37. init,
  38. start,
  39. stop,
  40. max
  41. };
  42. template<typename = void>
  43. inline constexpr std::string_view to_string(event_type v)
  44. {
  45. using namespace std::string_view_literals;
  46. switch (v)
  47. {
  48. case event_type::recv : return "recv";
  49. case event_type::send : return "send";
  50. case event_type::connect : return "connect";
  51. case event_type::disconnect : return "disconnect";
  52. case event_type::accept : return "accept";
  53. case event_type::handshake : return "handshake";
  54. case event_type::upgrade : return "upgrade";
  55. case event_type::init : return "init";
  56. case event_type::start : return "start";
  57. case event_type::stop : return "stop";
  58. case event_type::max : return "max";
  59. default : return "none";
  60. }
  61. return "none";
  62. }
  63. class observer_base
  64. {
  65. public:
  66. virtual ~observer_base() noexcept {}
  67. };
  68. template<class... Args>
  69. class observer_t : public observer_base
  70. {
  71. public:
  72. using func_type = std::function<void(Args...)>;
  73. using args_type = std::tuple<Args...>;
  74. explicit observer_t(const func_type & fn) : fn_(fn) {}
  75. explicit observer_t( func_type && fn) : fn_(std::move(fn)) {}
  76. explicit observer_t(const observer_t<Args...> & other) : fn_(other.fn_) {}
  77. explicit observer_t( observer_t<Args...> && other) : fn_(std::move(other.fn_)) {}
  78. template<class F, class ...C>
  79. explicit observer_t(F&& f, C&&... c)
  80. {
  81. this->bind(std::forward<F>(f), std::forward<C>(c)...);
  82. }
  83. template<class F, class ...C>
  84. inline void bind(F&& f, C&&... c)
  85. {
  86. if constexpr (sizeof...(C) == std::size_t(0))
  87. {
  88. this->fn_ = func_type(std::forward<F>(f));
  89. }
  90. else
  91. {
  92. if constexpr (std::is_member_function_pointer_v<detail::remove_cvref_t<F>>)
  93. {
  94. if constexpr (sizeof...(C) == std::size_t(1))
  95. {
  96. this->bind_memfn(std::forward<F>(f), std::forward<C>(c)...);
  97. }
  98. else
  99. {
  100. this->bind_memfn_front(std::forward<F>(f), std::forward<C>(c)...);
  101. }
  102. }
  103. else
  104. {
  105. this->bind_fn_front(std::forward<F>(f), std::forward<C>(c)...);
  106. }
  107. }
  108. }
  109. template<class F, class C>
  110. inline void bind_memfn(F&& f, C&& c)
  111. {
  112. if constexpr /**/ (std::is_pointer_v<detail::remove_cvref_t<C>>)
  113. {
  114. this->fn_ = [fn = std::forward<F>(f), s = std::forward<C>(c)](Args&&... args) mutable
  115. {
  116. (s->*fn)(std::forward<Args>(args)...);
  117. };
  118. }
  119. else if constexpr (std::is_reference_v<std::remove_cv_t<C>>)
  120. {
  121. this->fn_ = [fn = std::forward<F>(f), s = std::forward<C>(c)](Args&&... args) mutable
  122. {
  123. (s.*fn)(std::forward<Args>(args)...);
  124. };
  125. }
  126. else
  127. {
  128. static_assert(detail::always_false_v<F>,
  129. "the class object parameters of C&& c must be pointer or reference");
  130. }
  131. }
  132. template<class F, class C, class... Ts>
  133. inline void bind_memfn_front(F&& f, C&& c, Ts&&... ts)
  134. {
  135. if constexpr /**/ (std::is_pointer_v<detail::remove_cvref_t<C>>)
  136. {
  137. this->fn_ = [fn = std::forward<F>(f), s = std::forward<C>(c), tp = std::tuple(std::forward<Ts>(ts)...)]
  138. (Args&&... args) mutable
  139. {
  140. invoke_memfn_front(fn, s, std::make_index_sequence<sizeof...(Ts)>{}, tp, std::forward<Args>(args)...);
  141. };
  142. }
  143. else if constexpr (std::is_reference_v<std::remove_cv_t<C>>)
  144. {
  145. this->fn_ = [fn = std::forward<F>(f), s = std::forward<C>(c), tp = std::tuple(std::forward<Ts>(ts)...)]
  146. (Args&&... args) mutable
  147. {
  148. invoke_memfn_front(fn, std::addressof(s), std::make_index_sequence<sizeof...(Ts)>{}, tp, std::forward<Args>(args)...);
  149. };
  150. }
  151. else
  152. {
  153. static_assert(detail::always_false_v<F>,
  154. "the class object parameters of C&& c must be pointer or reference");
  155. }
  156. }
  157. template<typename F, typename C, std::size_t... I, typename... Ts>
  158. inline static void invoke_memfn_front(F& f, C* c, std::index_sequence<I...>, std::tuple<Ts...>& tp, Args&&... args)
  159. {
  160. (c->*f)(std::get<I>(tp)..., std::forward<Args>(args)...);
  161. }
  162. template<class F, class... Ts>
  163. inline void bind_fn_front(F&& f, Ts&&... ts)
  164. {
  165. this->fn_ = [fn = std::forward<F>(f), tp = std::tuple(std::forward<Ts>(ts)...)]
  166. (Args&&... args) mutable
  167. {
  168. invoke_fn_front(fn, std::make_index_sequence<sizeof...(Ts)>{}, tp, std::forward<Args>(args)...);
  169. };
  170. }
  171. template<typename F, std::size_t... I, typename... Ts>
  172. inline static void invoke_fn_front(F& f, std::index_sequence<I...>, std::tuple<Ts...>& tp, Args&&... args)
  173. {
  174. f(std::get<I>(tp)..., std::forward<Args>(args)...);
  175. }
  176. inline void operator()(Args&&... args)
  177. {
  178. if (this->fn_)
  179. this->fn_(std::forward<Args>(args)...);
  180. }
  181. inline func_type move() noexcept { return std::move(this->fn_); }
  182. protected:
  183. func_type fn_;
  184. };
  185. class listener_t
  186. {
  187. public:
  188. listener_t() {}
  189. ~listener_t() = default;
  190. template<class T>
  191. inline void bind(event_type e, T&& observer)
  192. {
  193. this->observers_[detail::to_underlying(e)] =
  194. std::unique_ptr<observer_base>(new T(std::forward<T>(observer)));
  195. }
  196. template<class... Args>
  197. inline void notify(event_type e, Args&&... args)
  198. {
  199. using observer_type = observer_t<Args...>;
  200. observer_type* observer_ptr = static_cast<observer_type*>(
  201. this->observers_[detail::to_underlying(e)].get());
  202. if (observer_ptr)
  203. {
  204. // You can define ASIO_NO_EXCEPTIONS in the /asio2/config.hpp to disable the
  205. // exception. so when the exception occurs, you can check the stack trace.
  206. #if !defined(ASIO_NO_EXCEPTIONS) && !defined(BOOST_ASIO_NO_EXCEPTIONS)
  207. try
  208. {
  209. #endif
  210. (*observer_ptr)(std::forward<Args>(args)...);
  211. #if !defined(ASIO_NO_EXCEPTIONS) && !defined(BOOST_ASIO_NO_EXCEPTIONS)
  212. }
  213. catch (system_error const& ex)
  214. {
  215. std::ignore = ex;
  216. #if defined(_DEBUG) || defined(DEBUG)
  217. // just for see the exception information.
  218. std::string msg = "An exception occured in the user callback function 'bind_";
  219. msg += detail::to_string(e);
  220. msg += "' : ";
  221. msg += ex.what();
  222. std::ignore = msg;
  223. #endif
  224. ASIO2_LOG_ERROR("An exception occured in the user callback function 'bind_{}' :1: {}",
  225. detail::to_string(e), ex.what());
  226. ASIO2_ASSERT(false);
  227. }
  228. catch (std::exception const& ex)
  229. {
  230. std::ignore = ex;
  231. #if defined(_DEBUG) || defined(DEBUG)
  232. // just for see the exception information.
  233. std::string msg = "An exception occured in the user callback function 'bind_";
  234. msg += detail::to_string(e);
  235. msg += "' : ";
  236. msg += ex.what();
  237. std::ignore = msg;
  238. #endif
  239. ASIO2_LOG_ERROR("An exception occured in the user callback function 'bind_{}' :2: {}",
  240. detail::to_string(e), ex.what());
  241. ASIO2_ASSERT(false);
  242. }
  243. catch (...)
  244. {
  245. #if defined(_DEBUG) || defined(DEBUG)
  246. // just for see the exception information.
  247. std::string msg = "An exception occured in the user callback function 'bind_";
  248. msg += detail::to_string(e);
  249. msg += "'";
  250. std::ignore = msg;
  251. #endif
  252. ASIO2_LOG_ERROR("An exception occured in the user callback function 'bind_{}' :3",
  253. detail::to_string(e));
  254. ASIO2_ASSERT(false);
  255. }
  256. #endif
  257. }
  258. }
  259. inline std::unique_ptr<observer_base>& find(event_type e) noexcept
  260. {
  261. return this->observers_[detail::to_underlying(e)];
  262. }
  263. inline std::unique_ptr<observer_base> const& find(event_type e) const noexcept
  264. {
  265. return this->observers_[detail::to_underlying(e)];
  266. }
  267. inline void clear() noexcept
  268. {
  269. for (std::unique_ptr<observer_base>& p : this->observers_)
  270. {
  271. p.reset();
  272. }
  273. }
  274. protected:
  275. std::array<std::unique_ptr<observer_base>, detail::to_underlying(event_type::max)> observers_;
  276. };
  277. }
  278. #endif // !__ASIO2_LISTENER_HPP__