This repository has been archived on 2023-11-05. You can view files and clone it, but cannot push or open issues or pull requests.
signal-wrangler/include/sgnl/SignalHandler.h
2019-09-14 22:41:56 +02:00

76 lines
1.6 KiB
C++

// Author: Thomas Trapp - https://thomastrapp.com/
// License: MIT
#pragma once
#include <sgnl/AtomicCondition.h>
#include <csignal>
#include <cstring>
#include <map>
#include <stdexcept>
#include <utility>
namespace sgnl {
class SignalHandlerException : public std::runtime_error
{
using std::runtime_error::runtime_error;
};
template<typename ValueType>
class SignalHandler
{
public:
SignalHandler(std::map<int, ValueType> signal_map,
AtomicCondition<ValueType>& 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<int, ValueType> signal_map_;
sigset_t set_;
AtomicCondition<ValueType>& condition_;
};
} // namespace sgnl