cmUVHandlePtr.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  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 "cm_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 insure the safe usage of uv_*_t types. This
  24. * includes making sure resources are properly freed and contains casting
  25. * operators which allow for passing into relevant uv_* functions.
  26. *
  27. *@tparam T actual uv_*_t type represented.
  28. */
  29. template <typename T>
  30. class uv_handle_ptr_base_
  31. {
  32. protected:
  33. template <typename _T>
  34. friend class uv_handle_ptr_base_;
  35. /**
  36. * This must be a pointer type since the handle can outlive this class.
  37. * When uv_close is eventually called on the handle, the memory the
  38. * handle inhabits must be valid until the close callback is called
  39. * which can be later on in the loop.
  40. */
  41. std::shared_ptr<T> handle;
  42. /**
  43. * Allocate memory for the type and optionally set it's 'data' pointer.
  44. * Protected since this should only be called for an appropriate 'init'
  45. * call.
  46. *
  47. * @param data data pointer to set
  48. */
  49. void allocate(void* data = nullptr);
  50. public:
  51. CM_DISABLE_COPY(uv_handle_ptr_base_)
  52. uv_handle_ptr_base_(uv_handle_ptr_base_&&) noexcept;
  53. uv_handle_ptr_base_& operator=(uv_handle_ptr_base_&&) noexcept;
  54. /**
  55. * This move constructor allows us to move out of a more specialized
  56. * uv type into a less specialized one. The only constraint is that
  57. * the right hand side is castable to T.
  58. *
  59. * This allows you to return uv_handle_ptr or uv_stream_ptr from a function
  60. * that initializes something like uv_pipe_ptr or uv_tcp_ptr and interact
  61. * and clean up after it without caring about the exact type.
  62. */
  63. template <typename S,
  64. typename = typename std::enable_if<
  65. std::is_rvalue_reference<S&&>::value>::type>
  66. uv_handle_ptr_base_(S&& rhs)
  67. {
  68. // This will force a compiler error if rhs doesn't have a casting
  69. // operator to get T*
  70. this->handle = std::shared_ptr<T>(rhs.handle, rhs);
  71. rhs.handle.reset();
  72. }
  73. // Dtor and ctor need to be inline defined like this for default ctors and
  74. // dtors to work.
  75. uv_handle_ptr_base_() {}
  76. uv_handle_ptr_base_(std::nullptr_t) {}
  77. ~uv_handle_ptr_base_() { reset(); }
  78. /**
  79. * Properly close the handle if needed and sets the inner handle to nullptr
  80. */
  81. void reset();
  82. /**
  83. * Allow less verbose calling of uv_handle_* functions
  84. * @return reinterpreted handle
  85. */
  86. operator uv_handle_t*();
  87. T* get() const;
  88. T* operator->() const noexcept;
  89. };
  90. template <typename T>
  91. inline uv_handle_ptr_base_<T>::uv_handle_ptr_base_(
  92. uv_handle_ptr_base_<T>&&) noexcept = default;
  93. template <typename T>
  94. inline uv_handle_ptr_base_<T>& uv_handle_ptr_base_<T>::operator=(
  95. uv_handle_ptr_base_<T>&&) noexcept = default;
  96. /**
  97. * While uv_handle_ptr_base_ only exposes uv_handle_t*, this exposes uv_T_t*
  98. * too. It is broken out like this so we can reuse most of the code for the
  99. * uv_handle_ptr class.
  100. */
  101. template <typename T>
  102. class uv_handle_ptr_ : public uv_handle_ptr_base_<T>
  103. {
  104. template <typename _T>
  105. friend class uv_handle_ptr_;
  106. public:
  107. CM_INHERIT_CTOR(uv_handle_ptr_, uv_handle_ptr_base_, <T>);
  108. /***
  109. * Allow less verbose calling of uv_<T> functions
  110. * @return reinterpreted handle
  111. */
  112. operator T*() const;
  113. };
  114. /***
  115. * This specialization is required to avoid duplicate 'operator uv_handle_t*()'
  116. * declarations
  117. */
  118. template <>
  119. class uv_handle_ptr_<uv_handle_t> : public uv_handle_ptr_base_<uv_handle_t>
  120. {
  121. public:
  122. CM_INHERIT_CTOR(uv_handle_ptr_, uv_handle_ptr_base_, <uv_handle_t>);
  123. };
  124. class uv_async_ptr : public uv_handle_ptr_<uv_async_t>
  125. {
  126. public:
  127. CM_INHERIT_CTOR(uv_async_ptr, uv_handle_ptr_, <uv_async_t>);
  128. int init(uv_loop_t& loop, uv_async_cb async_cb, void* data = nullptr);
  129. void send();
  130. };
  131. struct uv_signal_ptr : public uv_handle_ptr_<uv_signal_t>
  132. {
  133. CM_INHERIT_CTOR(uv_signal_ptr, uv_handle_ptr_, <uv_signal_t>);
  134. int init(uv_loop_t& loop, void* data = nullptr);
  135. int start(uv_signal_cb cb, int signum);
  136. void stop();
  137. };
  138. struct uv_pipe_ptr : public uv_handle_ptr_<uv_pipe_t>
  139. {
  140. CM_INHERIT_CTOR(uv_pipe_ptr, uv_handle_ptr_, <uv_pipe_t>);
  141. operator uv_stream_t*() const;
  142. int init(uv_loop_t& loop, int ipc, void* data = nullptr);
  143. };
  144. struct uv_process_ptr : public uv_handle_ptr_<uv_process_t>
  145. {
  146. CM_INHERIT_CTOR(uv_process_ptr, uv_handle_ptr_, <uv_process_t>);
  147. int spawn(uv_loop_t& loop, uv_process_options_t const& options,
  148. void* data = nullptr);
  149. };
  150. struct uv_timer_ptr : public uv_handle_ptr_<uv_timer_t>
  151. {
  152. CM_INHERIT_CTOR(uv_timer_ptr, uv_handle_ptr_, <uv_timer_t>);
  153. int init(uv_loop_t& loop, void* data = nullptr);
  154. int start(uv_timer_cb cb, uint64_t timeout, uint64_t repeat);
  155. };
  156. struct uv_tty_ptr : public uv_handle_ptr_<uv_tty_t>
  157. {
  158. CM_INHERIT_CTOR(uv_tty_ptr, uv_handle_ptr_, <uv_tty_t>);
  159. operator uv_stream_t*() const;
  160. int init(uv_loop_t& loop, int fd, int readable, void* data = nullptr);
  161. };
  162. typedef uv_handle_ptr_<uv_stream_t> uv_stream_ptr;
  163. typedef uv_handle_ptr_<uv_handle_t> uv_handle_ptr;
  164. #ifndef cmUVHandlePtr_cxx
  165. extern template class uv_handle_ptr_base_<uv_handle_t>;
  166. # define UV_HANDLE_PTR_INSTANTIATE_EXTERN(NAME) \
  167. extern template class uv_handle_ptr_base_<uv_##NAME##_t>; \
  168. extern template class uv_handle_ptr_<uv_##NAME##_t>;
  169. UV_HANDLE_PTR_INSTANTIATE_EXTERN(async)
  170. UV_HANDLE_PTR_INSTANTIATE_EXTERN(signal)
  171. UV_HANDLE_PTR_INSTANTIATE_EXTERN(pipe)
  172. UV_HANDLE_PTR_INSTANTIATE_EXTERN(process)
  173. UV_HANDLE_PTR_INSTANTIATE_EXTERN(stream)
  174. UV_HANDLE_PTR_INSTANTIATE_EXTERN(timer)
  175. UV_HANDLE_PTR_INSTANTIATE_EXTERN(tty)
  176. # undef UV_HANDLE_PTR_INSTANTIATE_EXTERN
  177. #endif
  178. }