|
|
@@ -0,0 +1,200 @@
|
|
|
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
|
|
+ file Copyright.txt or https://cmake.org/licensing for details. */
|
|
|
+#pragma once
|
|
|
+#include "cmConfigure.h" // IWYU pragma: keep
|
|
|
+
|
|
|
+#include <algorithm>
|
|
|
+#include <cstddef>
|
|
|
+#include <memory>
|
|
|
+#include <type_traits>
|
|
|
+
|
|
|
+#include "cm_uv.h"
|
|
|
+
|
|
|
+#define CM_PERFECT_FWD_CTOR(Class, FwdTo) \
|
|
|
+ template <typename... Args> \
|
|
|
+ Class(Args&&... args) \
|
|
|
+ : FwdTo(std::forward<Args>(args)...) \
|
|
|
+ { \
|
|
|
+ }
|
|
|
+
|
|
|
+namespace cm {
|
|
|
+
|
|
|
+/***
|
|
|
+* RAII class to simplify and insure the safe usage of uv_*_t types. This
|
|
|
+* includes making sure resources are properly freed and contains casting
|
|
|
+* operators which allow for passing into relevant uv_* functions.
|
|
|
+*
|
|
|
+*@tparam T actual uv_*_t type represented.
|
|
|
+*/
|
|
|
+template <typename T>
|
|
|
+class uv_handle_ptr_base_
|
|
|
+{
|
|
|
+protected:
|
|
|
+ template <typename _T>
|
|
|
+ friend class uv_handle_ptr_base_;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * This must be a pointer type since the handle can outlive this class.
|
|
|
+ * When uv_close is eventually called on the handle, the memory the
|
|
|
+ * handle inhabits must be valid until the close callback is called
|
|
|
+ * which can be later on in the loop.
|
|
|
+ */
|
|
|
+ std::shared_ptr<T> handle;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Allocate memory for the type and optionally set it's 'data' pointer.
|
|
|
+ * Protected since this should only be called for an appropriate 'init'
|
|
|
+ * call.
|
|
|
+ *
|
|
|
+ * @param data data pointer to set
|
|
|
+ */
|
|
|
+ void allocate(void* data = nullptr);
|
|
|
+
|
|
|
+public:
|
|
|
+ CM_DISABLE_COPY(uv_handle_ptr_base_)
|
|
|
+ uv_handle_ptr_base_(uv_handle_ptr_base_&&) noexcept;
|
|
|
+ uv_handle_ptr_base_& operator=(uv_handle_ptr_base_&&) noexcept;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * This move constructor allows us to move out of a more specialized
|
|
|
+ * uv type into a less specialized one. The only constraint is that
|
|
|
+ * the right hand side is castable to T.
|
|
|
+ *
|
|
|
+ * This allows you to return uv_handle_ptr or uv_stream_ptr from a function
|
|
|
+ * that initializes something like uv_pipe_ptr or uv_tcp_ptr and interact
|
|
|
+ * and clean up after it without caring about the exact type.
|
|
|
+ */
|
|
|
+ template <typename S, typename = typename std::enable_if<
|
|
|
+ std::is_rvalue_reference<S&&>::value>::type>
|
|
|
+ uv_handle_ptr_base_(S&& rhs)
|
|
|
+ {
|
|
|
+ // This will force a compiler error if rhs doesn't have a casting
|
|
|
+ // operator to get T*
|
|
|
+ this->handle = std::shared_ptr<T>(rhs.handle, rhs);
|
|
|
+ rhs.handle.reset();
|
|
|
+ }
|
|
|
+
|
|
|
+ // Dtor and ctor need to be inline defined like this for default ctors and
|
|
|
+ // dtors to work.
|
|
|
+ uv_handle_ptr_base_() {}
|
|
|
+ uv_handle_ptr_base_(std::nullptr_t) {}
|
|
|
+ ~uv_handle_ptr_base_() { reset(); }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Properly close the handle if needed and sets the inner handle to nullptr
|
|
|
+ */
|
|
|
+ void reset();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Allow less verbose calling of uv_handle_* functions
|
|
|
+ * @return reinterpreted handle
|
|
|
+ */
|
|
|
+ operator uv_handle_t*();
|
|
|
+
|
|
|
+ T* get() const;
|
|
|
+ T* operator->() const noexcept;
|
|
|
+};
|
|
|
+
|
|
|
+template <typename T>
|
|
|
+inline uv_handle_ptr_base_<T>::uv_handle_ptr_base_(
|
|
|
+ uv_handle_ptr_base_<T>&&) noexcept = default;
|
|
|
+template <typename T>
|
|
|
+inline uv_handle_ptr_base_<T>& uv_handle_ptr_base_<T>::operator=(
|
|
|
+ uv_handle_ptr_base_<T>&&) noexcept = default;
|
|
|
+
|
|
|
+/**
|
|
|
+ * While uv_handle_ptr_base_ only exposes uv_handle_t*, this exposes uv_T_t*
|
|
|
+ * too. It is broken out like this so we can reuse most of the code for the
|
|
|
+ * uv_handle_ptr class.
|
|
|
+ */
|
|
|
+template <typename T>
|
|
|
+class uv_handle_ptr_ : public uv_handle_ptr_base_<T>
|
|
|
+{
|
|
|
+ template <typename _T>
|
|
|
+ friend class uv_handle_ptr_;
|
|
|
+
|
|
|
+public:
|
|
|
+ CM_PERFECT_FWD_CTOR(uv_handle_ptr_, uv_handle_ptr_base_<T>);
|
|
|
+
|
|
|
+ /***
|
|
|
+ * Allow less verbose calling of uv_<T> functions
|
|
|
+ * @return reinterpreted handle
|
|
|
+ */
|
|
|
+ operator T*() const;
|
|
|
+};
|
|
|
+
|
|
|
+/***
|
|
|
+ * This specialization is required to avoid duplicate 'operator uv_handle_t*()'
|
|
|
+ * declarations
|
|
|
+ */
|
|
|
+template <>
|
|
|
+class uv_handle_ptr_<uv_handle_t> : public uv_handle_ptr_base_<uv_handle_t>
|
|
|
+{
|
|
|
+public:
|
|
|
+ CM_PERFECT_FWD_CTOR(uv_handle_ptr_, uv_handle_ptr_base_<uv_handle_t>);
|
|
|
+};
|
|
|
+
|
|
|
+class uv_async_ptr : public uv_handle_ptr_<uv_async_t>
|
|
|
+{
|
|
|
+public:
|
|
|
+ CM_PERFECT_FWD_CTOR(uv_async_ptr, uv_handle_ptr_<uv_async_t>);
|
|
|
+
|
|
|
+ int init(uv_loop_t& loop, uv_async_cb async_cb, void* data = nullptr);
|
|
|
+
|
|
|
+ void send();
|
|
|
+};
|
|
|
+
|
|
|
+struct uv_signal_ptr : public uv_handle_ptr_<uv_signal_t>
|
|
|
+{
|
|
|
+ CM_PERFECT_FWD_CTOR(uv_signal_ptr, uv_handle_ptr_<uv_signal_t>);
|
|
|
+
|
|
|
+ int init(uv_loop_t& loop, void* data = nullptr);
|
|
|
+
|
|
|
+ int start(uv_signal_cb cb, int signum);
|
|
|
+
|
|
|
+ void stop();
|
|
|
+};
|
|
|
+
|
|
|
+struct uv_pipe_ptr : public uv_handle_ptr_<uv_pipe_t>
|
|
|
+{
|
|
|
+ CM_PERFECT_FWD_CTOR(uv_pipe_ptr, uv_handle_ptr_<uv_pipe_t>);
|
|
|
+
|
|
|
+ operator uv_stream_t*() const;
|
|
|
+
|
|
|
+ int init(uv_loop_t& loop, int ipc, void* data = nullptr);
|
|
|
+};
|
|
|
+
|
|
|
+struct uv_tty_ptr : public uv_handle_ptr_<uv_tty_t>
|
|
|
+{
|
|
|
+ CM_PERFECT_FWD_CTOR(uv_tty_ptr, uv_handle_ptr_<uv_tty_t>);
|
|
|
+
|
|
|
+ operator uv_stream_t*() const;
|
|
|
+
|
|
|
+ int init(uv_loop_t& loop, int fd, int readable, void* data = nullptr);
|
|
|
+};
|
|
|
+
|
|
|
+typedef uv_handle_ptr_<uv_stream_t> uv_stream_ptr;
|
|
|
+typedef uv_handle_ptr_<uv_handle_t> uv_handle_ptr;
|
|
|
+
|
|
|
+#ifndef cmUVHandlePtr_cxx
|
|
|
+
|
|
|
+extern template class uv_handle_ptr_base_<uv_handle_t>;
|
|
|
+
|
|
|
+#define UV_HANDLE_PTR_INSTANTIATE_EXTERN(NAME) \
|
|
|
+ extern template class uv_handle_ptr_base_<uv_##NAME##_t>; \
|
|
|
+ extern template class uv_handle_ptr_<uv_##NAME##_t>;
|
|
|
+
|
|
|
+UV_HANDLE_PTR_INSTANTIATE_EXTERN(async)
|
|
|
+
|
|
|
+UV_HANDLE_PTR_INSTANTIATE_EXTERN(signal)
|
|
|
+
|
|
|
+UV_HANDLE_PTR_INSTANTIATE_EXTERN(pipe)
|
|
|
+
|
|
|
+UV_HANDLE_PTR_INSTANTIATE_EXTERN(stream)
|
|
|
+
|
|
|
+UV_HANDLE_PTR_INSTANTIATE_EXTERN(tty)
|
|
|
+
|
|
|
+#undef UV_HANDLE_PTR_INSTANTIATE_EXTERN
|
|
|
+
|
|
|
+#endif
|
|
|
+}
|