// Author: Thomas Trapp - https://thomastrapp.com/ // License: MIT #pragma once #include #include #include #include #include #include namespace sgnl { class SignalHandlerException : public std::runtime_error { using std::runtime_error::runtime_error; }; template class SignalHandler { public: SignalHandler(std::map signal_map, AtomicCondition& condition) : signal_map_(std::move(signal_map)) , set_() , condition_(condition) { if( sigemptyset(&this->set_) != 0 ) throw SignalHandlerException("sigemptyset error"); for( const auto& p : this->signal_map_ ) if( sigaddset(&this->set_, p.first) != 0 ) throw SignalHandlerException("sigaddset error"); int s = pthread_sigmask(SIG_BLOCK, &this->set_, nullptr); if( s != 0 ) throw SignalHandlerException( std::string("pthread_sigmask: ") + std::strerror(s)); } int operator()() { while( true ) { int signum = 0; int ret = sigwait(&this->set_, &signum); if( ret != 0 ) throw SignalHandlerException( std::string("sigwait: ") + std::strerror(ret)); if( auto it = this->signal_map_.find(signum); it != this->signal_map_.end() ) { this->condition_.set(it->second); this->condition_.notify_all(); return it->first; } } } private: std::map signal_map_; sigset_t set_; AtomicCondition& condition_; }; } // namespace sgnl