cmUVHandlePtr.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #pragma once
  4. #include "cmConfigure.h" // IWYU pragma: keep
  5. #include <cstddef>
  6. #include <cstdint>
  7. #include <memory>
  8. #include <type_traits>
  9. #include <cm3p/uv.h>
  10. #if defined(__SUNPRO_CC)
  11. # include <utility>
  12. # define CM_INHERIT_CTOR(Class, Base, Tpl) \
  13. template <typename... Args> \
  14. Class(Args&&... args) \
  15. : Base Tpl(std::forward<Args>(args)...) \
  16. { \
  17. }
  18. #else
  19. # define CM_INHERIT_CTOR(Class, Base, Tpl) using Base Tpl ::Base
  20. #endif
  21. namespace cm {
  22. /***
  23. * RAII class to simplify and ensure the safe usage of uv_loop_t. This includes
  24. * making sure resources are properly freed.
  25. */
  26. class uv_loop_ptr
  27. {
  28. protected:
  29. std::shared_ptr<uv_loop_t> loop;
  30. public:
  31. uv_loop_ptr(uv_loop_ptr const&) = delete;
  32. uv_loop_ptr& operator=(uv_loop_ptr const&) = delete;
  33. uv_loop_ptr(uv_loop_ptr&&) noexcept;
  34. uv_loop_ptr& operator=(uv_loop_ptr&&) noexcept;
  35. // Dtor and ctor need to be inline defined like this for default ctors and
  36. // dtors to work. Some compilers do not like '= default' here.
  37. uv_loop_ptr() {} // NOLINT(modernize-use-equals-default)
  38. uv_loop_ptr(std::nullptr_t) {}
  39. ~uv_loop_ptr() { this->reset(); }
  40. int init(void* data = nullptr);
  41. /**
  42. * Properly close the handle if needed and sets the inner handle to nullptr
  43. */
  44. void reset();
  45. /**
  46. * Allow less verbose calling of uv_loop_* functions
  47. * @return reinterpreted handle
  48. */
  49. operator uv_loop_t*() const;
  50. uv_loop_t* get() const;
  51. uv_loop_t* operator->() const noexcept;
  52. };
  53. /***
  54. * RAII class to simplify and ensure the safe usage of uv_*_t types. This
  55. * includes making sure resources are properly freed and contains casting
  56. * operators which allow for passing into relevant uv_* functions.
  57. *
  58. *@tparam T actual uv_*_t type represented.
  59. */
  60. template <typename T>
  61. class uv_handle_ptr_base_
  62. {
  63. protected:
  64. template <typename U>
  65. friend class uv_handle_ptr_base_;
  66. /**
  67. * This must be a pointer type since the handle can outlive this class.
  68. * When uv_close is eventually called on the handle, the memory the
  69. * handle inhabits must be valid until the close callback is called
  70. * which can be later on in the loop.
  71. */
  72. std::shared_ptr<T> handle;
  73. /**
  74. * Allocate memory for the type and optionally set it's 'data' pointer.
  75. * Protected since this should only be called for an appropriate 'init'
  76. * call.
  77. *
  78. * @param data data pointer to set
  79. */
  80. void allocate(void* data = nullptr);
  81. public:
  82. uv_handle_ptr_base_(uv_handle_ptr_base_ const&) = delete;
  83. uv_handle_ptr_base_& operator=(uv_handle_ptr_base_ const&) = delete;
  84. uv_handle_ptr_base_(uv_handle_ptr_base_&&) noexcept;
  85. uv_handle_ptr_base_& operator=(uv_handle_ptr_base_&&) noexcept;
  86. /**
  87. * This move constructor allows us to move out of a more specialized
  88. * uv type into a less specialized one. The only constraint is that
  89. * the right hand side is castable to T.
  90. *
  91. * This allows you to return uv_handle_ptr or uv_stream_ptr from a function
  92. * that initializes something like uv_pipe_ptr or uv_tcp_ptr and interact
  93. * and clean up after it without caring about the exact type.
  94. */
  95. template <typename S,
  96. typename = typename std::enable_if<
  97. std::is_rvalue_reference<S&&>::value>::type>
  98. uv_handle_ptr_base_(S&& rhs)
  99. {
  100. // This will force a compiler error if rhs doesn't have a casting
  101. // operator to get T*
  102. this->handle = std::shared_ptr<T>(rhs.handle, rhs);
  103. rhs.handle.reset();
  104. }
  105. // Dtor and ctor need to be inline defined like this for default ctors and
  106. // dtors to work. Some compilers do not like '= default' here.
  107. uv_handle_ptr_base_() {} // NOLINT(modernize-use-equals-default)
  108. uv_handle_ptr_base_(std::nullptr_t) {}
  109. ~uv_handle_ptr_base_() { this->reset(); }
  110. explicit operator bool() const;
  111. /**
  112. * Properly close the handle if needed and sets the inner handle to nullptr
  113. */
  114. void reset();
  115. /**
  116. * Allow less verbose calling of uv_handle_* functions
  117. * @return reinterpreted handle
  118. */
  119. operator uv_handle_t*() const;
  120. T* get() const;
  121. T* operator->() const noexcept;
  122. };
  123. template <typename T>
  124. inline uv_handle_ptr_base_<T>::uv_handle_ptr_base_(
  125. uv_handle_ptr_base_<T>&&) noexcept = default;
  126. template <typename T>
  127. inline uv_handle_ptr_base_<T>& uv_handle_ptr_base_<T>::operator=(
  128. uv_handle_ptr_base_<T>&&) noexcept = default;
  129. /**
  130. * While uv_handle_ptr_base_ only exposes uv_handle_t*, this exposes uv_T_t*
  131. * too. It is broken out like this so we can reuse most of the code for the
  132. * uv_handle_ptr class.
  133. */
  134. template <typename T>
  135. class uv_handle_ptr_ : public uv_handle_ptr_base_<T>
  136. {
  137. template <typename U>
  138. friend class uv_handle_ptr_;
  139. public:
  140. CM_INHERIT_CTOR(uv_handle_ptr_, uv_handle_ptr_base_, <T>);
  141. /***
  142. * Allow less verbose calling of uv_<T> functions
  143. * @return reinterpreted handle
  144. */
  145. operator T*() const;
  146. };
  147. /***
  148. * This specialization is required to avoid duplicate 'operator uv_handle_t*()'
  149. * declarations
  150. */
  151. template <>
  152. class uv_handle_ptr_<uv_handle_t> : public uv_handle_ptr_base_<uv_handle_t>
  153. {
  154. public:
  155. CM_INHERIT_CTOR(uv_handle_ptr_, uv_handle_ptr_base_, <uv_handle_t>);
  156. };
  157. class uv_async_ptr : public uv_handle_ptr_<uv_async_t>
  158. {
  159. public:
  160. CM_INHERIT_CTOR(uv_async_ptr, uv_handle_ptr_, <uv_async_t>);
  161. int init(uv_loop_t& loop, uv_async_cb async_cb, void* data = nullptr);
  162. void send();
  163. };
  164. struct uv_idle_ptr : public uv_handle_ptr_<uv_idle_t>
  165. {
  166. CM_INHERIT_CTOR(uv_idle_ptr, uv_handle_ptr_, <uv_idle_t>);
  167. int init(uv_loop_t& loop, void* data = nullptr);
  168. };
  169. struct uv_signal_ptr : public uv_handle_ptr_<uv_signal_t>
  170. {
  171. CM_INHERIT_CTOR(uv_signal_ptr, uv_handle_ptr_, <uv_signal_t>);
  172. int init(uv_loop_t& loop, void* data = nullptr);
  173. int start(uv_signal_cb cb, int signum);
  174. void stop();
  175. };
  176. struct uv_pipe_ptr : public uv_handle_ptr_<uv_pipe_t>
  177. {
  178. CM_INHERIT_CTOR(uv_pipe_ptr, uv_handle_ptr_, <uv_pipe_t>);
  179. operator uv_stream_t*() const;
  180. int init(uv_loop_t& loop, int ipc, void* data = nullptr);
  181. };
  182. struct uv_process_ptr : public uv_handle_ptr_<uv_process_t>
  183. {
  184. CM_INHERIT_CTOR(uv_process_ptr, uv_handle_ptr_, <uv_process_t>);
  185. int spawn(uv_loop_t& loop, uv_process_options_t const& options,
  186. void* data = nullptr);
  187. };
  188. struct uv_timer_ptr : public uv_handle_ptr_<uv_timer_t>
  189. {
  190. CM_INHERIT_CTOR(uv_timer_ptr, uv_handle_ptr_, <uv_timer_t>);
  191. int init(uv_loop_t& loop, void* data = nullptr);
  192. int start(uv_timer_cb cb, uint64_t timeout, uint64_t repeat);
  193. void stop();
  194. };
  195. struct uv_tty_ptr : public uv_handle_ptr_<uv_tty_t>
  196. {
  197. CM_INHERIT_CTOR(uv_tty_ptr, uv_handle_ptr_, <uv_tty_t>);
  198. operator uv_stream_t*() const;
  199. int init(uv_loop_t& loop, int fd, int readable, void* data = nullptr);
  200. };
  201. using uv_stream_ptr = uv_handle_ptr_<uv_stream_t>;
  202. using uv_handle_ptr = uv_handle_ptr_<uv_handle_t>;
  203. #ifndef cmUVHandlePtr_cxx
  204. extern template class uv_handle_ptr_base_<uv_handle_t>;
  205. # define UV_HANDLE_PTR_INSTANTIATE_EXTERN(NAME) \
  206. extern template class uv_handle_ptr_base_<uv_##NAME##_t>; \
  207. extern template class uv_handle_ptr_<uv_##NAME##_t>;
  208. UV_HANDLE_PTR_INSTANTIATE_EXTERN(async)
  209. UV_HANDLE_PTR_INSTANTIATE_EXTERN(idle)
  210. UV_HANDLE_PTR_INSTANTIATE_EXTERN(signal)
  211. UV_HANDLE_PTR_INSTANTIATE_EXTERN(pipe)
  212. UV_HANDLE_PTR_INSTANTIATE_EXTERN(process)
  213. UV_HANDLE_PTR_INSTANTIATE_EXTERN(stream)
  214. UV_HANDLE_PTR_INSTANTIATE_EXTERN(timer)
  215. UV_HANDLE_PTR_INSTANTIATE_EXTERN(tty)
  216. # undef UV_HANDLE_PTR_INSTANTIATE_EXTERN
  217. #endif
  218. }