From f33e820a160243438587d8a24b8ac306d05638e5 Mon Sep 17 00:00:00 2001 From: Tom Date: Sun, 13 Oct 2019 15:06:50 +0200 Subject: [PATCH] add example using threads --- CMakeLists.txt | 3 ++ README.md | 3 ++ example/example.cpp | 78 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 example/example.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c033096..4335f43 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,3 +42,6 @@ install(EXPORT SgnlTargets add_subdirectory("test") +add_executable(example EXCLUDE_FROM_ALL "example/example.cpp") +target_link_libraries(example sgnl::sgnl) + diff --git a/README.md b/README.md index 1fd88fe..8785e2d 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ Signal handler that uses [pthread_sigmask](http://man7.org/linux/man-pages/man3/ int last_signal = signal_handler.sigwait_handler(handler); } // signals are unblocked again ``` +See [example.cpp](example/example.cpp) for an example using threads. ## Build & Install @@ -45,6 +46,8 @@ mkdir -p build/ && cd build/ cmake .. # build and run tests make sgnl-test && ./test/sgnl-test +# build and run example +make example && ./example # install headers and CMake config make install ``` diff --git a/example/example.cpp b/example/example.cpp new file mode 100644 index 0000000..afcec40 --- /dev/null +++ b/example/example.cpp @@ -0,0 +1,78 @@ +#include +#include + +#include +#include +#include +#include + + +void Worker(const sgnl::AtomicCondition& exit_condition) +{ + auto predicate = [&exit_condition]() { + return exit_condition.get(); + }; + while( true ) + { + exit_condition.wait_for(std::chrono::minutes(1), predicate); + if( exit_condition.get() ) + return; + /* ... do work ... */ + } +} + +int main() +{ + sgnl::AtomicCondition exit_condition(false); + + auto handler = [&exit_condition](int signum) { + std::cout << "received signal " << signum << "\n"; + if( signum == SIGTERM || signum == SIGINT ) + { + exit_condition.set(true); + // wakeup all waiting threads + exit_condition.notify_all(); + // stop polling for signals + return true; + } + + // continue waiting for signals + return false; + }; + + // Block signals in this thread. + // Threads spawned later will inherit the signal mask. + sgnl::SignalHandler signal_handler({SIGINT, SIGTERM, SIGUSR1}); + + std::future ft_sig_handler = + std::async( + std::launch::async, + &sgnl::SignalHandler::sigwait_handler, + &signal_handler, + std::ref(handler)); + + std::vector> futures; + for(int i = 0; i < 10; ++i) + futures.push_back( + std::async( + std::launch::async, + Worker, + std::ref(exit_condition))); + + // SIGUSR1 + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + kill(0, SIGUSR1); + + // SIGTERM + kill(0, SIGTERM); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + for(auto& future : futures) + future.wait(); + + int last_signal = ft_sig_handler.get(); + std::cout << "exiting (received signal " << last_signal << ")\n"; + + return EXIT_SUCCESS; +} +