cmUVHandlePtr.cxx 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #define cmUVHandlePtr_cxx
  4. #include "cmUVHandlePtr.h"
  5. #include <assert.h>
  6. #include <mutex>
  7. #include <stdlib.h>
  8. #include "cm_uv.h"
  9. namespace cm {
  10. static void close_delete(uv_handle_t* h)
  11. {
  12. free(h);
  13. }
  14. template <typename T>
  15. static void default_delete(T* type_handle)
  16. {
  17. auto handle = reinterpret_cast<uv_handle_t*>(type_handle);
  18. if (handle) {
  19. assert(!uv_is_closing(handle));
  20. if (!uv_is_closing(handle)) {
  21. uv_close(handle, &close_delete);
  22. }
  23. }
  24. }
  25. /**
  26. * Encapsulates delete logic for a given handle type T
  27. */
  28. template <typename T>
  29. struct uv_handle_deleter
  30. {
  31. void operator()(T* type_handle) const { default_delete(type_handle); }
  32. };
  33. template <typename T>
  34. void uv_handle_ptr_base_<T>::allocate(void* data)
  35. {
  36. reset();
  37. /*
  38. We use calloc since we know all these types are c structs
  39. and we just want to 0 init them. New would do the same thing;
  40. but casting from uv_handle_t to certain other types -- namely
  41. uv_timer_t -- triggers a cast_align warning on certain systems.
  42. */
  43. handle.reset(static_cast<T*>(calloc(1, sizeof(T))), uv_handle_deleter<T>());
  44. handle->data = data;
  45. }
  46. template <typename T>
  47. void uv_handle_ptr_base_<T>::reset()
  48. {
  49. handle.reset();
  50. }
  51. template <typename T>
  52. uv_handle_ptr_base_<T>::operator uv_handle_t*()
  53. {
  54. return reinterpret_cast<uv_handle_t*>(handle.get());
  55. }
  56. template <typename T>
  57. T* uv_handle_ptr_base_<T>::operator->() const noexcept
  58. {
  59. return handle.get();
  60. }
  61. template <typename T>
  62. T* uv_handle_ptr_base_<T>::get() const
  63. {
  64. return handle.get();
  65. }
  66. template <typename T>
  67. uv_handle_ptr_<T>::operator T*() const
  68. {
  69. return this->handle.get();
  70. }
  71. #ifdef CMAKE_BUILD_WITH_CMAKE
  72. template <>
  73. struct uv_handle_deleter<uv_async_t>
  74. {
  75. /***
  76. * Wile uv_async_send is itself thread-safe, there are
  77. * no strong guarantees that close hasn't already been
  78. * called on the handle; and that it might be deleted
  79. * as the send call goes through. This mutex guards
  80. * against that.
  81. *
  82. * The shared_ptr here is to allow for copy construction
  83. * which is mandated by the standard for Deleter on
  84. * shared_ptrs.
  85. */
  86. std::shared_ptr<std::mutex> handleMutex;
  87. uv_handle_deleter()
  88. : handleMutex(std::make_shared<std::mutex>())
  89. {
  90. }
  91. void operator()(uv_async_t* handle)
  92. {
  93. std::lock_guard<std::mutex> lock(*handleMutex);
  94. default_delete(handle);
  95. }
  96. };
  97. void uv_async_ptr::send()
  98. {
  99. auto deleter = std::get_deleter<uv_handle_deleter<uv_async_t>>(this->handle);
  100. assert(deleter);
  101. std::lock_guard<std::mutex> lock(*deleter->handleMutex);
  102. if (this->handle) {
  103. uv_async_send(*this);
  104. }
  105. }
  106. int uv_async_ptr::init(uv_loop_t& loop, uv_async_cb async_cb, void* data)
  107. {
  108. allocate(data);
  109. return uv_async_init(&loop, handle.get(), async_cb);
  110. }
  111. #endif
  112. template <>
  113. struct uv_handle_deleter<uv_signal_t>
  114. {
  115. void operator()(uv_signal_t* handle) const
  116. {
  117. if (handle) {
  118. uv_signal_stop(handle);
  119. default_delete(handle);
  120. }
  121. }
  122. };
  123. int uv_signal_ptr::init(uv_loop_t& loop, void* data)
  124. {
  125. allocate(data);
  126. return uv_signal_init(&loop, handle.get());
  127. }
  128. int uv_signal_ptr::start(uv_signal_cb cb, int signum)
  129. {
  130. assert(handle);
  131. return uv_signal_start(*this, cb, signum);
  132. }
  133. void uv_signal_ptr::stop()
  134. {
  135. if (handle) {
  136. uv_signal_stop(*this);
  137. }
  138. }
  139. int uv_pipe_ptr::init(uv_loop_t& loop, int ipc, void* data)
  140. {
  141. allocate(data);
  142. return uv_pipe_init(&loop, *this, ipc);
  143. }
  144. uv_pipe_ptr::operator uv_stream_t*() const
  145. {
  146. return reinterpret_cast<uv_stream_t*>(handle.get());
  147. }
  148. #ifdef CMAKE_BUILD_WITH_CMAKE
  149. int uv_process_ptr::spawn(uv_loop_t& loop, uv_process_options_t const& options,
  150. void* data)
  151. {
  152. allocate(data);
  153. return uv_spawn(&loop, *this, &options);
  154. }
  155. int uv_timer_ptr::init(uv_loop_t& loop, void* data)
  156. {
  157. allocate(data);
  158. return uv_timer_init(&loop, *this);
  159. }
  160. int uv_timer_ptr::start(uv_timer_cb cb, uint64_t timeout, uint64_t repeat)
  161. {
  162. assert(handle);
  163. return uv_timer_start(*this, cb, timeout, repeat);
  164. }
  165. uv_tty_ptr::operator uv_stream_t*() const
  166. {
  167. return reinterpret_cast<uv_stream_t*>(handle.get());
  168. }
  169. int uv_tty_ptr::init(uv_loop_t& loop, int fd, int readable, void* data)
  170. {
  171. allocate(data);
  172. return uv_tty_init(&loop, *this, fd, readable);
  173. }
  174. #endif
  175. template class uv_handle_ptr_base_<uv_handle_t>;
  176. #define UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(NAME) \
  177. template class uv_handle_ptr_base_<uv_##NAME##_t>; \
  178. template class uv_handle_ptr_<uv_##NAME##_t>;
  179. UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(signal)
  180. UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(pipe)
  181. UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(stream)
  182. #ifdef CMAKE_BUILD_WITH_CMAKE
  183. UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(async)
  184. UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(process)
  185. UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(timer)
  186. UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(tty)
  187. #endif
  188. }