mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-11 16:32:14 -06:00
cmUVHandlePtr: Add cm::uv_loop_ptr
This commit is contained in:
@@ -11,19 +11,59 @@
|
||||
|
||||
namespace cm {
|
||||
|
||||
static void close_delete(uv_handle_t* h)
|
||||
struct uv_loop_deleter
|
||||
{
|
||||
free(h);
|
||||
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();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void default_delete(T* type_handle)
|
||||
static void handle_default_delete(T* type_handle)
|
||||
{
|
||||
auto handle = reinterpret_cast<uv_handle_t*>(type_handle);
|
||||
if (handle) {
|
||||
assert(!uv_is_closing(handle));
|
||||
if (!uv_is_closing(handle)) {
|
||||
uv_close(handle, &close_delete);
|
||||
uv_close(handle, [](uv_handle_t* h) { free(h); });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,7 +74,7 @@ static void default_delete(T* type_handle)
|
||||
template <typename T>
|
||||
struct uv_handle_deleter
|
||||
{
|
||||
void operator()(T* type_handle) const { default_delete(type_handle); }
|
||||
void operator()(T* type_handle) const { handle_default_delete(type_handle); }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@@ -107,7 +147,7 @@ struct uv_handle_deleter<uv_async_t>
|
||||
void operator()(uv_async_t* handle)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(*handleMutex);
|
||||
default_delete(handle);
|
||||
handle_default_delete(handle);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -136,7 +176,7 @@ struct uv_handle_deleter<uv_signal_t>
|
||||
{
|
||||
if (handle) {
|
||||
uv_signal_stop(handle);
|
||||
default_delete(handle);
|
||||
handle_default_delete(handle);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -30,7 +30,45 @@
|
||||
namespace cm {
|
||||
|
||||
/***
|
||||
* RAII class to simplify and insure the safe usage of uv_*_t types. This
|
||||
* RAII class to simplify and ensure the safe usage of uv_loop_t. This includes
|
||||
* making sure resources are properly freed.
|
||||
*/
|
||||
class uv_loop_ptr
|
||||
{
|
||||
protected:
|
||||
std::shared_ptr<uv_loop_t> loop;
|
||||
|
||||
public:
|
||||
uv_loop_ptr(uv_loop_ptr const&) = delete;
|
||||
uv_loop_ptr& operator=(uv_loop_ptr const&) = delete;
|
||||
uv_loop_ptr(uv_loop_ptr&&) noexcept;
|
||||
uv_loop_ptr& operator=(uv_loop_ptr&&) noexcept;
|
||||
|
||||
// Dtor and ctor need to be inline defined like this for default ctors and
|
||||
// dtors to work. Some compilers do not like '= default' here.
|
||||
uv_loop_ptr() {} // NOLINT(modernize-use-equals-default)
|
||||
uv_loop_ptr(std::nullptr_t) {}
|
||||
~uv_loop_ptr() { this->reset(); }
|
||||
|
||||
int init(void* data = nullptr);
|
||||
|
||||
/**
|
||||
* Properly close the handle if needed and sets the inner handle to nullptr
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/**
|
||||
* Allow less verbose calling of uv_loop_* functions
|
||||
* @return reinterpreted handle
|
||||
*/
|
||||
operator uv_loop_t*();
|
||||
|
||||
uv_loop_t* get() const;
|
||||
uv_loop_t* operator->() const noexcept;
|
||||
};
|
||||
|
||||
/***
|
||||
* RAII class to simplify and ensure 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.
|
||||
*
|
||||
|
||||
@@ -171,11 +171,59 @@ static bool testAllMoves()
|
||||
return true;
|
||||
};
|
||||
|
||||
static bool testLoopReset()
|
||||
{
|
||||
bool closed = false;
|
||||
cm::uv_loop_ptr loop;
|
||||
loop.init();
|
||||
|
||||
uv_timer_t timer;
|
||||
uv_timer_init(loop, &timer);
|
||||
timer.data = &closed;
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(&timer), [](uv_handle_t* handle) {
|
||||
auto closedPtr = static_cast<bool*>(handle->data);
|
||||
*closedPtr = true;
|
||||
});
|
||||
|
||||
loop.reset();
|
||||
if (!closed) {
|
||||
std::cerr << "uv_loop_ptr did not finish" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
static bool testLoopDestructor()
|
||||
{
|
||||
bool closed = false;
|
||||
|
||||
uv_timer_t timer;
|
||||
{
|
||||
cm::uv_loop_ptr loop;
|
||||
loop.init();
|
||||
|
||||
uv_timer_init(loop, &timer);
|
||||
timer.data = &closed;
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(&timer), [](uv_handle_t* handle) {
|
||||
auto closedPtr = static_cast<bool*>(handle->data);
|
||||
*closedPtr = true;
|
||||
});
|
||||
}
|
||||
|
||||
if (!closed) {
|
||||
std::cerr << "uv_loop_ptr did not finish" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
int testUVRAII(int, char** const)
|
||||
{
|
||||
if ((testAsyncShutdown() &&
|
||||
testAsyncDtor() & testAsyncMove() & testCrossAssignment() &
|
||||
testAllMoves()) == 0) {
|
||||
testAllMoves() & testLoopReset() & testLoopDestructor()) == 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user