#include <sys/time.h>
+#include <assert.h>
+
#if 1 // older unices need these includes for select (2)
# include <unistd.h>
# include <sys/types.h>
// until that happens, sys/select.h must come last
#include <sys/select.h>
+// for IOM_SIG
+#include <signal.h>
+
#include "iom.h"
// TSTAMP_MAX must still fit into a positive struct timeval
tw0 ()
: time_watcher (this, &tw0::cb)
- { }}
-tw0;
+ { }
+ } tw0;
tstamp NOW;
static bool iom_valid;
gettimeofday (&tv, 0);
NOW = (tstamp)tv.tv_sec + (tstamp)tv.tv_usec / 1000000;
+}
#endif
+
+#if IOM_SIG
+// race conditions galore
+
+void io_manager::sighandler (int signum)
+{
+ assert (0 < signum && signum <= iom.sw.size ());
+
+ sig_vec &sv = *iom.sw [signum - 1];
+
+ for (int i = sv.size (); i--; )
+ if (!sv[i])
+ sv.erase_unordered (i);
+ else
+ sv[i]->call (*sv[i]);
}
+void io_manager::reg (sig_watcher *w)
+{
+ assert (0 < w->signum);
+
+ sw.reserve (w->signum);
+
+ sig_vec *&sv = sw [w->signum - 1];
+
+ if (!sv)
+ {
+ sv = new sig_vec;
+
+ struct sigaction sa;
+ sa.sa_handler = io_manager::sighandler;
+ sigfillset (&sa.sa_mask);
+ sa.sa_flags = 0;
+
+ if (sigaction (w->signum, &sa, 0))
+ {
+ perror ("Error while installing signal handler");
+ abort ();
+ }
+ }
+
+ reg (w, *sv);
+}
+
+void io_manager::unreg (sig_watcher *w)
+{
+ assert (0 < w->signum && w->signum <= sw.size ());
+
+ unreg (w, *sw [w->signum - 1]);
+}
+
+void sig_watcher::start (int signum)
+{
+ stop ();
+ this->signum = signum;
+ iom.reg (this);
+}
+#endif
+
void io_manager::loop ()
{
#if IOM_TIME
#ifndef IOM_IDLE
# define IOM_IDLE 0
#endif
+#ifndef IOM_SIG
+# define IOM_SIG 0
+#endif
typedef double tstamp;
extern tstamp NOW;
#if IOM_IDLE
struct idle_watcher;
#endif
+#if IOM_SIG
+struct sig_watcher;
+#endif
template<class watcher>
struct io_manager_vec : vector<watcher *> {
#if IOM_IDLE
io_manager_vec<idle_watcher> iw;
#endif
+#if IOM_SIG
+ typedef io_manager_vec<sig_watcher> sig_vec;
+ vector<sig_vec *> sw;
+ static void sighandler (int signum);
+#endif
template<class watcher>
void reg (watcher *w, io_manager_vec<watcher> &queue);
#if IOM_IDLE
void reg (idle_watcher *w); void unreg (idle_watcher *w);
#endif
+#if IOM_SIG
+ void reg (sig_watcher *w); void unreg (sig_watcher *w);
+#endif
void loop ();
};
#endif
+#if IOM_SIG
+struct sig_watcher : watcher, callback1<void, sig_watcher &> {
+ int signum;
+
+ void start (int signum);
+ void stop () { iom.unreg (this); }
+
+ template<class O1, class O2>
+ sig_watcher (O1 *object, void (O2::*method) (sig_watcher &))
+ : callback1<void, sig_watcher &> (object,method), signum (-1)
+ { }
+ ~sig_watcher () { stop (); }
+};
+#endif
+
#endif