cmake/Source/cmUVHandlePtr.cxx

270 lines
5.7 KiB
C++
Raw Normal View History

2018-04-23 21:13:27 +02:00
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#define cmUVHandlePtr_cxx
#include "cmUVHandlePtr.h"
2020-02-01 23:06:01 +01:00
#include <cassert>
#include <cstdlib>
2018-04-23 21:13:27 +02:00
#include <mutex>
2020-08-30 11:54:41 +02:00
#include <cm3p/uv.h>
2018-04-23 21:13:27 +02:00
namespace cm {
2019-11-11 23:01:05 +01:00
struct uv_loop_deleter
2018-04-23 21:13:27 +02:00
{
2019-11-11 23:01:05 +01:00
void operator()(uv_loop_t* loop) const;
};
void uv_loop_deleter::operator()(uv_loop_t* loop) const
{
uv_run(loop, UV_RUN_DEFAULT);
int result = uv_loop_close(loop);
(void)result;
assert(result >= 0);
free(loop);
}
int uv_loop_ptr::init(void* data)
{
this->reset();
this->loop.reset(static_cast<uv_loop_t*>(calloc(1, sizeof(uv_loop_t))),
uv_loop_deleter());
this->loop->data = data;
return uv_loop_init(this->loop.get());
}
void uv_loop_ptr::reset()
{
this->loop.reset();
}
uv_loop_ptr::operator uv_loop_t*()
{
return this->loop.get();
}
uv_loop_t* uv_loop_ptr::operator->() const noexcept
{
return this->loop.get();
}
uv_loop_t* uv_loop_ptr::get() const
{
return this->loop.get();
2018-04-23 21:13:27 +02:00
}
template <typename T>
2019-11-11 23:01:05 +01:00
static void handle_default_delete(T* type_handle)
2018-04-23 21:13:27 +02:00
{
2021-09-14 00:13:48 +02:00
auto* handle = reinterpret_cast<uv_handle_t*>(type_handle);
2018-04-23 21:13:27 +02:00
if (handle) {
assert(!uv_is_closing(handle));
if (!uv_is_closing(handle)) {
2019-11-11 23:01:05 +01:00
uv_close(handle, [](uv_handle_t* h) { free(h); });
2018-04-23 21:13:27 +02:00
}
}
}
/**
* Encapsulates delete logic for a given handle type T
*/
template <typename T>
struct uv_handle_deleter
{
2019-11-11 23:01:05 +01:00
void operator()(T* type_handle) const { handle_default_delete(type_handle); }
2018-04-23 21:13:27 +02:00
};
template <typename T>
void uv_handle_ptr_base_<T>::allocate(void* data)
{
2021-09-14 00:13:48 +02:00
this->reset();
2018-04-23 21:13:27 +02:00
/*
We use calloc since we know all these types are c structs
and we just want to 0 init them. New would do the same thing;
but casting from uv_handle_t to certain other types -- namely
uv_timer_t -- triggers a cast_align warning on certain systems.
*/
2021-09-14 00:13:48 +02:00
this->handle.reset(static_cast<T*>(calloc(1, sizeof(T))),
uv_handle_deleter<T>());
this->handle->data = data;
2018-04-23 21:13:27 +02:00
}
template <typename T>
void uv_handle_ptr_base_<T>::reset()
{
2021-09-14 00:13:48 +02:00
this->handle.reset();
2018-04-23 21:13:27 +02:00
}
template <typename T>
uv_handle_ptr_base_<T>::operator uv_handle_t*()
{
2021-09-14 00:13:48 +02:00
return reinterpret_cast<uv_handle_t*>(this->handle.get());
2018-04-23 21:13:27 +02:00
}
template <typename T>
T* uv_handle_ptr_base_<T>::operator->() const noexcept
{
2021-09-14 00:13:48 +02:00
return this->handle.get();
2018-04-23 21:13:27 +02:00
}
template <typename T>
T* uv_handle_ptr_base_<T>::get() const
{
2021-09-14 00:13:48 +02:00
return this->handle.get();
2018-04-23 21:13:27 +02:00
}
template <typename T>
uv_handle_ptr_<T>::operator T*() const
{
return this->handle.get();
}
2020-02-01 23:06:01 +01:00
#ifndef CMAKE_BOOTSTRAP
2018-04-23 21:13:27 +02:00
template <>
struct uv_handle_deleter<uv_async_t>
{
/***
2021-09-14 00:13:48 +02:00
* While uv_async_send is itself thread-safe, there are
2018-08-09 18:06:22 +02:00
* no strong guarantees that close hasn't already been
* called on the handle; and that it might be deleted
* as the send call goes through. This mutex guards
* against that.
*
* The shared_ptr here is to allow for copy construction
* which is mandated by the standard for Deleter on
* shared_ptrs.
*/
2018-04-23 21:13:27 +02:00
std::shared_ptr<std::mutex> handleMutex;
uv_handle_deleter()
: handleMutex(std::make_shared<std::mutex>())
{
}
void operator()(uv_async_t* handle)
{
2021-09-14 00:13:48 +02:00
std::lock_guard<std::mutex> lock(*this->handleMutex);
2019-11-11 23:01:05 +01:00
handle_default_delete(handle);
2018-04-23 21:13:27 +02:00
}
};
void uv_async_ptr::send()
{
2021-09-14 00:13:48 +02:00
auto* deleter =
std::get_deleter<uv_handle_deleter<uv_async_t>>(this->handle);
2018-04-23 21:13:27 +02:00
assert(deleter);
std::lock_guard<std::mutex> lock(*deleter->handleMutex);
if (this->handle) {
uv_async_send(*this);
}
}
int uv_async_ptr::init(uv_loop_t& loop, uv_async_cb async_cb, void* data)
{
2021-09-14 00:13:48 +02:00
this->allocate(data);
return uv_async_init(&loop, this->handle.get(), async_cb);
2018-04-23 21:13:27 +02:00
}
#endif
template <>
struct uv_handle_deleter<uv_signal_t>
{
void operator()(uv_signal_t* handle) const
{
if (handle) {
uv_signal_stop(handle);
2019-11-11 23:01:05 +01:00
handle_default_delete(handle);
2018-04-23 21:13:27 +02:00
}
}
};
int uv_signal_ptr::init(uv_loop_t& loop, void* data)
{
2021-09-14 00:13:48 +02:00
this->allocate(data);
return uv_signal_init(&loop, this->handle.get());
2018-04-23 21:13:27 +02:00
}
int uv_signal_ptr::start(uv_signal_cb cb, int signum)
{
2021-09-14 00:13:48 +02:00
assert(this->handle);
2018-04-23 21:13:27 +02:00
return uv_signal_start(*this, cb, signum);
}
void uv_signal_ptr::stop()
{
2021-09-14 00:13:48 +02:00
if (this->handle) {
2018-04-23 21:13:27 +02:00
uv_signal_stop(*this);
}
}
int uv_pipe_ptr::init(uv_loop_t& loop, int ipc, void* data)
{
2021-09-14 00:13:48 +02:00
this->allocate(data);
2018-04-23 21:13:27 +02:00
return uv_pipe_init(&loop, *this, ipc);
}
uv_pipe_ptr::operator uv_stream_t*() const
{
2021-09-14 00:13:48 +02:00
return reinterpret_cast<uv_stream_t*>(this->handle.get());
2018-04-23 21:13:27 +02:00
}
int uv_process_ptr::spawn(uv_loop_t& loop, uv_process_options_t const& options,
void* data)
{
2021-09-14 00:13:48 +02:00
this->allocate(data);
2018-04-23 21:13:27 +02:00
return uv_spawn(&loop, *this, &options);
}
int uv_timer_ptr::init(uv_loop_t& loop, void* data)
{
2021-09-14 00:13:48 +02:00
this->allocate(data);
2018-04-23 21:13:27 +02:00
return uv_timer_init(&loop, *this);
}
int uv_timer_ptr::start(uv_timer_cb cb, uint64_t timeout, uint64_t repeat)
{
2021-09-14 00:13:48 +02:00
assert(this->handle);
2018-04-23 21:13:27 +02:00
return uv_timer_start(*this, cb, timeout, repeat);
}
2020-02-01 23:06:01 +01:00
#ifndef CMAKE_BOOTSTRAP
2018-04-23 21:13:27 +02:00
uv_tty_ptr::operator uv_stream_t*() const
{
2021-09-14 00:13:48 +02:00
return reinterpret_cast<uv_stream_t*>(this->handle.get());
2018-04-23 21:13:27 +02:00
}
int uv_tty_ptr::init(uv_loop_t& loop, int fd, int readable, void* data)
{
2021-09-14 00:13:48 +02:00
this->allocate(data);
2018-04-23 21:13:27 +02:00
return uv_tty_init(&loop, *this, fd, readable);
}
#endif
template class uv_handle_ptr_base_<uv_handle_t>;
#define UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(NAME) \
template class uv_handle_ptr_base_<uv_##NAME##_t>; \
template class uv_handle_ptr_<uv_##NAME##_t>;
UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(signal)
UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(pipe)
UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(stream)
UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(process)
UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(timer)
2020-02-01 23:06:01 +01:00
#ifndef CMAKE_BOOTSTRAP
2019-11-11 23:01:05 +01:00
UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(async)
2018-04-23 21:13:27 +02:00
UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(tty)
#endif
}