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