Utils: Add singleton alive test member
[senf.git] / Scheduler / SignalEvent.cc
similarity index 54%
rename from Scheduler/SignalDispatcher.cc
rename to Scheduler/SignalEvent.cc
index 69d72bc..f083852 100644 (file)
 /** \file
     \brief SignalDispatcher non-inline non-template implementation */
 
-#include "SignalDispatcher.hh"
-//#include "SignalDispatcher.ih"
+#include "SignalEvent.hh"
+#include "SignalEvent.ih"
 
 // Custom includes
 #include "../Utils/senfassert.hh"
+#include "../Utils/signalnames.hh"
 
-//#include "SignalDispatcher.mpp"
+//#include "SignalEvent.mpp"
 #define prefix_
 ///////////////////////////////cc.p////////////////////////////////////////
 
-senf::scheduler::SignalDispatcher * senf::scheduler::SignalDispatcher::instance_ = 0;
-
-prefix_ senf::scheduler::SignalDispatcher::SignalDispatcher(FdManager & manager,
-                                                            FIFORunner & runner)
-    : manager_ (manager), runner_ (runner), blocked_ (true)
+prefix_ senf::scheduler::detail::SignalDispatcher::SignalDispatcher()
+    : blocked_ (true)
 {
-    SENF_ASSERT( !instance_ );
     if (pipe(sigPipe_) <0)
         SENF_THROW_SYSTEM_EXCEPTION("pipe()");
     sigemptyset(&sigSet_);
-    instance_ = this;
-    manager_.set(sigPipe_[0], FdManager::EV_READ, this);
+    FdManager::instance().set(sigPipe_[0], FdManager::EV_READ, this);
 }
 
-prefix_ senf::scheduler::SignalDispatcher::~SignalDispatcher()
+prefix_ senf::scheduler::detail::SignalDispatcher::~SignalDispatcher()
 {
-    for (HandlerMap::iterator i (handlers_.begin()); i != handlers_.end(); ++i) {
-        ::signal(i->first, SIG_DFL);
-        runner_.dequeue(&i->second);
+    for (SignalSet::iterator i (handlers_.begin()); i != handlers_.end(); ++i) {
+        ::signal(i->signal_, SIG_DFL);
+        FIFORunner::instance().dequeue(&(*i));
     }
     sigprocmask(SIG_UNBLOCK, &sigSet_, 0);
-    manager_.remove(sigPipe_[0]);
+    FdManager::instance().remove(sigPipe_[0]);
     close(sigPipe_[0]);
     close(sigPipe_[1]);
-    instance_ = 0;
 }
 
-prefix_ void senf::scheduler::SignalDispatcher::add(int signal, Callback const & cb)
+prefix_ void senf::scheduler::detail::SignalDispatcher::add(SignalEvent & event)
 {
-    HandlerMap::iterator i (handlers_.find(signal));
-    if (i != handlers_.end()) {
-        i->second.cb = cb;
-        return;
-    }
+    SignalSet::iterator i (handlers_.find(event));
+    if (i != handlers_.end())
+        throw DuplicateSignalRegistrationException() 
+            << " for signal " << signalName(event.signal_) << " (" << event.signal_ << ")";
 
-    i = handlers_.insert(std::make_pair(signal, SignalEvent(signal, cb))).first;
-    sigaddset(&sigSet_, signal);
-    runner_.enqueue(&i->second);
+    handlers_.insert(event);
+    sigaddset(&sigSet_, event.signal_);
+    FIFORunner::instance().enqueue(&event);
 
     sigset_t sig;
     sigemptyset(&sig);
-    sigaddset(&sig, signal);
+    sigaddset(&sig, event.signal_);
     sigprocmask(blocked_ ? SIG_BLOCK : SIG_UNBLOCK, &sig, 0);
 
     // Need to re-register all handlers to update sa_mask
-    for (HandlerMap::iterator j (handlers_.begin()); i != handlers_.end(); ++i) {
-        struct sigaction act;
-        act.sa_sigaction = &sigHandler;
-        act.sa_mask = sigSet_;
-        act.sa_flags = SA_SIGINFO | SA_RESTART;
-        if (j->first == SIGCLD)
+    struct sigaction act;
+    act.sa_sigaction = &sigHandler;
+    act.sa_mask = sigSet_;
+    act.sa_flags = SA_SIGINFO | SA_RESTART;
+    for (SignalSet::iterator i (handlers_.begin()); i != handlers_.end(); ++i) {
+        if (i->signal_ == SIGCLD)
             act.sa_flags |= SA_NOCLDSTOP;
-        if (sigaction(j->first, &act, 0) < 0)
+        else
+            act.sa_flags &= ~SA_NOCLDSTOP;
+        if (sigaction(i->signal_, &act, 0) < 0)
             SENF_THROW_SYSTEM_EXCEPTION("sigaction()");
     }
 }
 
-prefix_ void senf::scheduler::SignalDispatcher::remove(int signal)
+prefix_ void senf::scheduler::detail::SignalDispatcher::remove(SignalEvent & event)
 {
-    ::signal(signal, SIG_DFL);
+    ::signal(event.signal_, SIG_DFL);
+    FIFORunner::instance().dequeue(&event);
+    handlers_.erase(event);
     sigset_t sig;
     sigemptyset(&sig);
-    sigaddset(&sig, signal);
+    sigaddset(&sig, event.signal_);
     sigprocmask(SIG_UNBLOCK, &sig, 0);
 }
 
-prefix_ void senf::scheduler::SignalDispatcher::signal(int events)
+prefix_ void senf::scheduler::detail::SignalDispatcher::signal(int events)
 {
     siginfo_t info;
     if (read(sigPipe_[0], &info, sizeof(info)) < int(sizeof(info)))
         return;
-    HandlerMap::iterator i (handlers_.find(info.si_signo));
+    SignalSet::iterator i (handlers_.find(info.si_signo, FindNumericSignal()));
     if (i == handlers_.end())
         return;
-    i->second.siginfo = info;
-    i->second.runnable = true;
+    i->siginfo_ = info;
+    i->runnable = true;
 }
 
-prefix_ void senf::scheduler::SignalDispatcher::sigHandler(int signal, ::siginfo_t * siginfo,
+prefix_ void senf::scheduler::detail::SignalDispatcher::sigHandler(int signal, ::siginfo_t * siginfo,
                                                            void *)
 {
-    SENF_ASSERT( instance_ );
+    SENF_ASSERT( alive() );
     // The manpage says, si_signo is unused in linux so we set it here
     siginfo->si_signo = signal; 
     // We can't do much on error anyway so we ignore errors here
-    write(instance_->sigPipe_[1], siginfo, sizeof(*siginfo));
+    write(instance().sigPipe_[1], siginfo, sizeof(*siginfo));
 }
 
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
-//#include "SignalDispatcher.mpp"
+//#include "SignalEvent.mpp"
 
 \f
 // Local Variables: