123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- /* 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 <cstdint>
- #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_process_ptr : public uv_handle_ptr_<uv_process_t>
- {
- CM_PERFECT_FWD_CTOR(uv_process_ptr, uv_handle_ptr_<uv_process_t>);
- int spawn(uv_loop_t& loop, uv_process_options_t const& options,
- void* data = nullptr);
- };
- struct uv_timer_ptr : public uv_handle_ptr_<uv_timer_t>
- {
- CM_PERFECT_FWD_CTOR(uv_timer_ptr, uv_handle_ptr_<uv_timer_t>);
- int init(uv_loop_t& loop, void* data = nullptr);
- int start(uv_timer_cb cb, uint64_t timeout, uint64_t repeat);
- };
- 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(process)
- UV_HANDLE_PTR_INSTANTIATE_EXTERN(stream)
- UV_HANDLE_PTR_INSTANTIATE_EXTERN(timer)
- UV_HANDLE_PTR_INSTANTIATE_EXTERN(tty)
- #undef UV_HANDLE_PTR_INSTANTIATE_EXTERN
- #endif
- }
|