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