From 32cfa7b324de799eefb2f7370fb54b700d1a87a5 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 30 Nov 2017 11:11:54 -0500 Subject: cmUVHandlePtr: Move to CMakeLib to make it available everywhere --- Source/CMakeLists.txt | 3 +- Source/cmUVHandlePtr.cxx | 10 +- Tests/CMakeLib/CMakeLists.txt | 4 + Tests/CMakeLib/testUVRAII.cxx | 179 ++++++++++++++++++++++++++++++++++++ Tests/CMakeServerLib/CMakeLists.txt | 1 - Tests/CMakeServerLib/testUVRAII.cxx | 179 ------------------------------------ bootstrap | 1 + 7 files changed, 194 insertions(+), 183 deletions(-) create mode 100644 Tests/CMakeLib/testUVRAII.cxx delete mode 100644 Tests/CMakeServerLib/testUVRAII.cxx diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 88c63e1..5611e55 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -348,6 +348,8 @@ set(SRCS cmTestGenerator.cxx cmTestGenerator.h cmUuid.cxx + cmUVHandlePtr.cxx + cmUVHandlePtr.h cmVariableWatch.cxx cmVariableWatch.h cmVersion.cxx @@ -1029,7 +1031,6 @@ list(APPEND _tools cmake) target_link_libraries(cmake CMakeLib) add_library(CMakeServerLib - cmUVHandlePtr.h cmUVHandlePtr.cxx cmConnection.h cmConnection.cxx cmFileMonitor.cxx cmFileMonitor.h cmPipeConnection.cxx cmPipeConnection.h diff --git a/Source/cmUVHandlePtr.cxx b/Source/cmUVHandlePtr.cxx index 214c7b2..8ba93e5 100644 --- a/Source/cmUVHandlePtr.cxx +++ b/Source/cmUVHandlePtr.cxx @@ -82,6 +82,7 @@ uv_handle_ptr_::operator T*() const return this->handle.get(); } +#ifdef CMAKE_BUILD_WITH_CMAKE template <> struct uv_handle_deleter { @@ -126,6 +127,7 @@ int uv_async_ptr::init(uv_loop_t& loop, uv_async_cb async_cb, void* data) allocate(data); return uv_async_init(&loop, handle.get(), async_cb); } +#endif template <> struct uv_handle_deleter @@ -169,6 +171,7 @@ uv_pipe_ptr::operator uv_stream_t*() const return reinterpret_cast(handle.get()); } +#ifdef CMAKE_BUILD_WITH_CMAKE uv_tty_ptr::operator uv_stream_t*() const { return reinterpret_cast(handle.get()); @@ -179,6 +182,7 @@ int uv_tty_ptr::init(uv_loop_t& loop, int fd, int readable, void* data) allocate(data); return uv_tty_init(&loop, *this, fd, readable); } +#endif template class uv_handle_ptr_base_; @@ -186,13 +190,15 @@ template class uv_handle_ptr_base_; template class uv_handle_ptr_base_; \ template class uv_handle_ptr_; -UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(async) - UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(signal) UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(pipe) UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(stream) +#ifdef CMAKE_BUILD_WITH_CMAKE +UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(async) + UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(tty) +#endif } diff --git a/Tests/CMakeLib/CMakeLists.txt b/Tests/CMakeLib/CMakeLists.txt index d1a1df5..9f09185 100644 --- a/Tests/CMakeLib/CMakeLists.txt +++ b/Tests/CMakeLib/CMakeLists.txt @@ -12,6 +12,7 @@ set(CMakeLib_TESTS testXMLParser testXMLSafe testFindPackageCommand + testUVRAII ) set(testRST_ARGS ${CMAKE_CURRENT_SOURCE_DIR}) @@ -31,6 +32,9 @@ create_test_sourcelist(CMakeLib_TEST_SRCS CMakeLibTests.cxx ${CMakeLib_TESTS}) add_executable(CMakeLibTests ${CMakeLib_TEST_SRCS}) target_link_libraries(CMakeLibTests CMakeLib) +set_property(TARGET CMakeLibTests PROPERTY C_CLANG_TIDY "") +set_property(TARGET CMakeLibTests PROPERTY CXX_CLANG_TIDY "") + add_executable(testEncoding testEncoding.cxx) target_link_libraries(testEncoding cmsys) diff --git a/Tests/CMakeLib/testUVRAII.cxx b/Tests/CMakeLib/testUVRAII.cxx new file mode 100644 index 0000000..7ecef39 --- /dev/null +++ b/Tests/CMakeLib/testUVRAII.cxx @@ -0,0 +1,179 @@ +#include "cmUVHandlePtr.h" + +#include +#include +#include +#include + +#include "cm_uv.h" + +static void signal_reset_fn(uv_async_t* handle) +{ + auto ptr = static_cast(handle->data); + ptr->reset(); +} + +// A common pattern is to use an async signal to shutdown the server. +static bool testAsyncShutdown() +{ + uv_loop_t Loop; + auto err = uv_loop_init(&Loop); + if (err != 0) { + std::cerr << "Could not init loop" << std::endl; + return false; + } + + { + cm::uv_async_ptr signal; + signal.init(Loop, &signal_reset_fn, &signal); + + std::thread([&] { + std::this_thread::sleep_for(std::chrono::seconds(2)); + signal.send(); + }).detach(); + + if (uv_run(&Loop, UV_RUN_DEFAULT) != 0) { + std::cerr << "Unclean exit state in testAsyncDtor" << std::endl; + return false; + } + + if (signal.get()) { + std::cerr << "Loop exited with signal not being cleaned up" << std::endl; + return false; + } + } + + uv_loop_close(&Loop); + + return true; +} + +static void signal_fn(uv_async_t*) +{ +} + +// Async dtor is sort of a pain; since it locks a mutex we must be sure its +// dtor always calls reset otherwise the mutex is deleted then locked. +static bool testAsyncDtor() +{ + uv_loop_t Loop; + auto err = uv_loop_init(&Loop); + if (err != 0) { + std::cerr << "Could not init loop" << std::endl; + return false; + } + + { + cm::uv_async_ptr signal; + signal.init(Loop, signal_fn); + } + + if (uv_run(&Loop, UV_RUN_DEFAULT) != 0) { + std::cerr << "Unclean exit state in testAsyncDtor" << std::endl; + return false; + } + + uv_loop_close(&Loop); + + return true; +} + +// Async needs a relatively stateful deleter; make sure that is properly +// accounted for and doesn't try to hold on to invalid state when it is +// moved +static bool testAsyncMove() +{ + uv_loop_t Loop; + auto err = uv_loop_init(&Loop); + if (err != 0) { + std::cerr << "Could not init loop" << std::endl; + return false; + } + + { + cm::uv_async_ptr signal; + { + cm::uv_async_ptr signalTmp; + signalTmp.init(Loop, signal_fn); + signal = std::move(signalTmp); + } + } + + if (uv_run(&Loop, UV_RUN_DEFAULT) != 0) { + std::cerr << "Unclean exit state in testAsyncDtor" << std::endl; + return false; + } + + uv_loop_close(&Loop); + return true; +} + +// When a type is castable to another uv type (pipe -> stream) here, +// and the deleter is convertible as well, we should allow moves from +// one type to the other. +static bool testCrossAssignment() +{ + uv_loop_t Loop; + auto err = uv_loop_init(&Loop); + if (err != 0) { + std::cerr << "Could not init loop" << std::endl; + return false; + } + + { + cm::uv_pipe_ptr pipe; + pipe.init(Loop, 0); + + cm::uv_stream_ptr stream = std::move(pipe); + if (pipe.get()) { + std::cerr << "Move should be sure to invalidate the previous ptr" + << std::endl; + return false; + } + cm::uv_handle_ptr handle = std::move(stream); + if (stream.get()) { + std::cerr << "Move should be sure to invalidate the previous ptr" + << std::endl; + return false; + } + } + + if (uv_run(&Loop, UV_RUN_DEFAULT) != 0) { + std::cerr << "Unclean exit state in testCrossAssignment" << std::endl; + return false; + } + + uv_loop_close(&Loop); + return true; +} + +// This test can't fail at run time; but this makes sure we have all our move +// ctors created correctly. +static bool testAllMoves() +{ + using namespace cm; + struct allTypes + { + uv_stream_ptr _7; + uv_tty_ptr _9; + uv_pipe_ptr _12; + uv_async_ptr _13; + uv_signal_ptr _14; + uv_handle_ptr _15; + }; + + allTypes a; + allTypes b(std::move(a)); + allTypes c = std::move(b); + return true; +}; + +int testUVRAII(int, char** const) +{ + if ((testAsyncShutdown() && + testAsyncDtor() & testAsyncMove() & testCrossAssignment() & + testAllMoves()) == 0) { + return -1; + } + return 0; +} diff --git a/Tests/CMakeServerLib/CMakeLists.txt b/Tests/CMakeServerLib/CMakeLists.txt index f1ca2a4..5e1ad0c 100644 --- a/Tests/CMakeServerLib/CMakeLists.txt +++ b/Tests/CMakeServerLib/CMakeLists.txt @@ -6,7 +6,6 @@ include_directories( set(CMakeServerLib_TESTS testServerBuffering - testUVRAII ) create_test_sourcelist(CMakeLib_TEST_SRCS CMakeServerLibTests.cxx ${CMakeServerLib_TESTS}) diff --git a/Tests/CMakeServerLib/testUVRAII.cxx b/Tests/CMakeServerLib/testUVRAII.cxx deleted file mode 100644 index 7ecef39..0000000 --- a/Tests/CMakeServerLib/testUVRAII.cxx +++ /dev/null @@ -1,179 +0,0 @@ -#include "cmUVHandlePtr.h" - -#include -#include -#include -#include - -#include "cm_uv.h" - -static void signal_reset_fn(uv_async_t* handle) -{ - auto ptr = static_cast(handle->data); - ptr->reset(); -} - -// A common pattern is to use an async signal to shutdown the server. -static bool testAsyncShutdown() -{ - uv_loop_t Loop; - auto err = uv_loop_init(&Loop); - if (err != 0) { - std::cerr << "Could not init loop" << std::endl; - return false; - } - - { - cm::uv_async_ptr signal; - signal.init(Loop, &signal_reset_fn, &signal); - - std::thread([&] { - std::this_thread::sleep_for(std::chrono::seconds(2)); - signal.send(); - }).detach(); - - if (uv_run(&Loop, UV_RUN_DEFAULT) != 0) { - std::cerr << "Unclean exit state in testAsyncDtor" << std::endl; - return false; - } - - if (signal.get()) { - std::cerr << "Loop exited with signal not being cleaned up" << std::endl; - return false; - } - } - - uv_loop_close(&Loop); - - return true; -} - -static void signal_fn(uv_async_t*) -{ -} - -// Async dtor is sort of a pain; since it locks a mutex we must be sure its -// dtor always calls reset otherwise the mutex is deleted then locked. -static bool testAsyncDtor() -{ - uv_loop_t Loop; - auto err = uv_loop_init(&Loop); - if (err != 0) { - std::cerr << "Could not init loop" << std::endl; - return false; - } - - { - cm::uv_async_ptr signal; - signal.init(Loop, signal_fn); - } - - if (uv_run(&Loop, UV_RUN_DEFAULT) != 0) { - std::cerr << "Unclean exit state in testAsyncDtor" << std::endl; - return false; - } - - uv_loop_close(&Loop); - - return true; -} - -// Async needs a relatively stateful deleter; make sure that is properly -// accounted for and doesn't try to hold on to invalid state when it is -// moved -static bool testAsyncMove() -{ - uv_loop_t Loop; - auto err = uv_loop_init(&Loop); - if (err != 0) { - std::cerr << "Could not init loop" << std::endl; - return false; - } - - { - cm::uv_async_ptr signal; - { - cm::uv_async_ptr signalTmp; - signalTmp.init(Loop, signal_fn); - signal = std::move(signalTmp); - } - } - - if (uv_run(&Loop, UV_RUN_DEFAULT) != 0) { - std::cerr << "Unclean exit state in testAsyncDtor" << std::endl; - return false; - } - - uv_loop_close(&Loop); - return true; -} - -// When a type is castable to another uv type (pipe -> stream) here, -// and the deleter is convertible as well, we should allow moves from -// one type to the other. -static bool testCrossAssignment() -{ - uv_loop_t Loop; - auto err = uv_loop_init(&Loop); - if (err != 0) { - std::cerr << "Could not init loop" << std::endl; - return false; - } - - { - cm::uv_pipe_ptr pipe; - pipe.init(Loop, 0); - - cm::uv_stream_ptr stream = std::move(pipe); - if (pipe.get()) { - std::cerr << "Move should be sure to invalidate the previous ptr" - << std::endl; - return false; - } - cm::uv_handle_ptr handle = std::move(stream); - if (stream.get()) { - std::cerr << "Move should be sure to invalidate the previous ptr" - << std::endl; - return false; - } - } - - if (uv_run(&Loop, UV_RUN_DEFAULT) != 0) { - std::cerr << "Unclean exit state in testCrossAssignment" << std::endl; - return false; - } - - uv_loop_close(&Loop); - return true; -} - -// This test can't fail at run time; but this makes sure we have all our move -// ctors created correctly. -static bool testAllMoves() -{ - using namespace cm; - struct allTypes - { - uv_stream_ptr _7; - uv_tty_ptr _9; - uv_pipe_ptr _12; - uv_async_ptr _13; - uv_signal_ptr _14; - uv_handle_ptr _15; - }; - - allTypes a; - allTypes b(std::move(a)); - allTypes c = std::move(b); - return true; -}; - -int testUVRAII(int, char** const) -{ - if ((testAsyncShutdown() && - testAsyncDtor() & testAsyncMove() & testCrossAssignment() & - testAllMoves()) == 0) { - return -1; - } - return 0; -} diff --git a/bootstrap b/bootstrap index ab087e9..45f9c2d 100755 --- a/bootstrap +++ b/bootstrap @@ -418,6 +418,7 @@ CMAKE_CXX_SOURCES="\ cmTryRunCommand \ cmUnexpectedCommand \ cmUnsetCommand \ + cmUVHandlePtr \ cmVersion \ cmWhileCommand \ cmWorkingDirectory \ -- cgit v0.12 From dd700e9bfb2a498632845e76ce95dd38bb866a7b Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 30 Nov 2017 11:19:04 -0500 Subject: cmUVHandlePtr: Add uv_timer_ptr --- Source/cmUVHandlePtr.cxx | 14 ++++++++++++++ Source/cmUVHandlePtr.h | 12 ++++++++++++ Tests/CMakeLib/testUVRAII.cxx | 1 + 3 files changed, 27 insertions(+) diff --git a/Source/cmUVHandlePtr.cxx b/Source/cmUVHandlePtr.cxx index 8ba93e5..78819a5 100644 --- a/Source/cmUVHandlePtr.cxx +++ b/Source/cmUVHandlePtr.cxx @@ -172,6 +172,18 @@ uv_pipe_ptr::operator uv_stream_t*() const } #ifdef CMAKE_BUILD_WITH_CMAKE +int uv_timer_ptr::init(uv_loop_t& loop, void* data) +{ + allocate(data); + return uv_timer_init(&loop, *this); +} + +int uv_timer_ptr::start(uv_timer_cb cb, uint64_t timeout, uint64_t repeat) +{ + assert(handle); + return uv_timer_start(*this, cb, timeout, repeat); +} + uv_tty_ptr::operator uv_stream_t*() const { return reinterpret_cast(handle.get()); @@ -199,6 +211,8 @@ UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(stream) #ifdef CMAKE_BUILD_WITH_CMAKE UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(async) +UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(timer) + UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(tty) #endif } diff --git a/Source/cmUVHandlePtr.h b/Source/cmUVHandlePtr.h index a251c5f..d3df69c 100644 --- a/Source/cmUVHandlePtr.h +++ b/Source/cmUVHandlePtr.h @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -164,6 +165,15 @@ struct uv_pipe_ptr : public uv_handle_ptr_ int init(uv_loop_t& loop, int ipc, void* data = nullptr); }; +struct uv_timer_ptr : public uv_handle_ptr_ +{ + CM_PERFECT_FWD_CTOR(uv_timer_ptr, uv_handle_ptr_); + + 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_ { CM_PERFECT_FWD_CTOR(uv_tty_ptr, uv_handle_ptr_); @@ -192,6 +202,8 @@ UV_HANDLE_PTR_INSTANTIATE_EXTERN(pipe) UV_HANDLE_PTR_INSTANTIATE_EXTERN(stream) +UV_HANDLE_PTR_INSTANTIATE_EXTERN(timer) + UV_HANDLE_PTR_INSTANTIATE_EXTERN(tty) #undef UV_HANDLE_PTR_INSTANTIATE_EXTERN diff --git a/Tests/CMakeLib/testUVRAII.cxx b/Tests/CMakeLib/testUVRAII.cxx index 7ecef39..bb3493f 100644 --- a/Tests/CMakeLib/testUVRAII.cxx +++ b/Tests/CMakeLib/testUVRAII.cxx @@ -155,6 +155,7 @@ static bool testAllMoves() struct allTypes { uv_stream_ptr _7; + uv_timer_ptr _8; uv_tty_ptr _9; uv_pipe_ptr _12; uv_async_ptr _13; -- cgit v0.12 From 3bcaa870078d875b65f17d82661a133f6d5cbdfc Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 30 Nov 2017 11:26:25 -0500 Subject: cmUVHandlePtr: Add uv_process_ptr --- Source/cmUVHandlePtr.cxx | 9 +++++++++ Source/cmUVHandlePtr.h | 10 ++++++++++ Tests/CMakeLib/testUVRAII.cxx | 1 + 3 files changed, 20 insertions(+) diff --git a/Source/cmUVHandlePtr.cxx b/Source/cmUVHandlePtr.cxx index 78819a5..d7e38c3 100644 --- a/Source/cmUVHandlePtr.cxx +++ b/Source/cmUVHandlePtr.cxx @@ -172,6 +172,13 @@ uv_pipe_ptr::operator uv_stream_t*() const } #ifdef CMAKE_BUILD_WITH_CMAKE +int uv_process_ptr::spawn(uv_loop_t& loop, uv_process_options_t const& options, + void* data) +{ + allocate(data); + return uv_spawn(&loop, *this, &options); +} + int uv_timer_ptr::init(uv_loop_t& loop, void* data) { allocate(data); @@ -211,6 +218,8 @@ UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(stream) #ifdef CMAKE_BUILD_WITH_CMAKE UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(async) +UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(process) + UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(timer) UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(tty) diff --git a/Source/cmUVHandlePtr.h b/Source/cmUVHandlePtr.h index d3df69c..a6ce565 100644 --- a/Source/cmUVHandlePtr.h +++ b/Source/cmUVHandlePtr.h @@ -165,6 +165,14 @@ struct uv_pipe_ptr : public uv_handle_ptr_ int init(uv_loop_t& loop, int ipc, void* data = nullptr); }; +struct uv_process_ptr : public uv_handle_ptr_ +{ + CM_PERFECT_FWD_CTOR(uv_process_ptr, uv_handle_ptr_); + + int spawn(uv_loop_t& loop, uv_process_options_t const& options, + void* data = nullptr); +}; + struct uv_timer_ptr : public uv_handle_ptr_ { CM_PERFECT_FWD_CTOR(uv_timer_ptr, uv_handle_ptr_); @@ -200,6 +208,8 @@ 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) diff --git a/Tests/CMakeLib/testUVRAII.cxx b/Tests/CMakeLib/testUVRAII.cxx index bb3493f..44def25 100644 --- a/Tests/CMakeLib/testUVRAII.cxx +++ b/Tests/CMakeLib/testUVRAII.cxx @@ -157,6 +157,7 @@ static bool testAllMoves() uv_stream_ptr _7; uv_timer_ptr _8; uv_tty_ptr _9; + uv_process_ptr _11; uv_pipe_ptr _12; uv_async_ptr _13; uv_signal_ptr _14; -- cgit v0.12