*** empty log message ***
authorroot <root>
Thu, 25 Oct 2007 12:42:00 +0000 (12:42 +0000)
committerroot <root>
Thu, 25 Oct 2007 12:42:00 +0000 (12:42 +0000)
src/iom.C
src/iom.h

index 69775517607a20ef04c2b26fed0f368ed55ff004..1c9fa8e9b7ef1e23a12cf56c50641add2fe63d3b 100644 (file)
--- a/src/iom.C
+++ b/src/iom.C
 #define TV_FRAC tv_usec
 #define TV_MULT 1000000L
 
-#ifndef IOM_LIBEVENT
-#if IOM_IO
-static io_manager_vec<io_watcher>    iow;
-#endif
-#if IOM_TIME
-static io_manager_vec<time_watcher>  tw;
-#endif
-#endif
-
 #if IOM_CHECK
 static io_manager_vec<check_watcher> cw;
 #endif
@@ -83,6 +74,36 @@ static vector<sig_vec *> sw;
 static io_manager_vec<child_watcher>  pw;
 #endif
 
+#ifdef IOM_LIBEVENT
+static bool need_set_now; // need to set_now in callback
+#else
+  #if IOM_IO
+  static io_manager_vec<io_watcher>    iow;
+  #endif
+  #if IOM_TIME
+  static io_manager_vec<time_watcher>  tw;
+  #endif
+#endif
+
+#if IOM_TIME
+tstamp io_manager::now ()
+{
+  struct timeval tv;
+
+  gettimeofday (&tv, 0);
+  return (tstamp)tv.tv_sec + (tstamp)tv.tv_usec / 1000000.;
+}
+
+void io_manager::set_now ()
+{
+  NOW = now ();
+  #ifdef IOM_LIBEVENT
+  need_set_now = false;
+  #endif
+}
+#endif
+
+#ifndef IOM_LIBEVENT
 // this is a dummy time watcher to ensure that the first
 // time watcher is _always_ valid, this gets rid of a lot
 // of null-pointer-checks
@@ -101,6 +122,7 @@ static struct tw0 : time_watcher
   : time_watcher (this, &tw0::cb)
   { }
 } tw0;
+#endif
 
 tstamp NOW;
 
@@ -135,61 +157,49 @@ static struct sw0 : sig_watcher
 } sw0;
 #endif
 
-#if IOM_TIME
-tstamp io_manager::now ()
-{
-  struct timeval tv;
-
-  gettimeofday (&tv, 0);
-  return (tstamp)tv.tv_sec + (tstamp)tv.tv_usec / 1000000.;
-}
-
-void io_manager::set_now ()
-{
-  NOW = now ();
-}
-#endif
-
 static bool iom_valid;
 
 // used for initialisation only
 static struct init {
   init ()
   {
-#ifdef IOM_PREINIT
-    { IOM_PREINIT }
-#endif
-#ifdef IOM_LIBEVENT
-    event_init ();
-#endif
+    #ifdef IOM_PREINIT
+      { IOM_PREINIT }
+    #endif
+
+    #ifdef IOM_LIBEVENT
+      event_init ();
+    #endif
     iom_valid = true;
 
-#if IOM_SIG
-    sigemptyset (&sigs);
+    #if IOM_SIG
+      sigemptyset (&sigs);
 
-    if (pipe (sigpipe))
-      {
-        perror ("io_manager: unable to create signal pipe, aborting.");
-        abort ();
-      }
+      if (pipe (sigpipe))
+        {
+          perror ("io_manager: unable to create signal pipe, aborting.");
+          abort ();
+        }
 
-    fcntl (sigpipe[0], F_SETFL, O_NONBLOCK); fcntl (sigpipe[0], F_SETFD, FD_CLOEXEC);
-    fcntl (sigpipe[1], F_SETFL, O_NONBLOCK); fcntl (sigpipe[1], F_SETFD, FD_CLOEXEC);
-#endif
+      fcntl (sigpipe[0], F_SETFL, O_NONBLOCK); fcntl (sigpipe[0], F_SETFD, FD_CLOEXEC);
+      fcntl (sigpipe[1], F_SETFL, O_NONBLOCK); fcntl (sigpipe[1], F_SETFD, FD_CLOEXEC);
+    #endif
 
-#if IOM_CHILD
-    sw0.start (SIGCHLD);
-#endif
+    #if IOM_CHILD
+      sw0.start (SIGCHLD);
+    #endif
 
-#if IOM_TIME
-    io_manager::set_now ();
+    #if IOM_TIME
+      io_manager::set_now ();
 
-    tw0.start (TSTAMP_MAX);
-#endif
+      #ifndef IOM_LIBEVENT
+        tw0.start (TSTAMP_MAX);
+      #endif
+    #endif
 
-#ifdef IOM_POSTINIT
-    { IOM_POSTINIT }
-#endif
+    #ifdef IOM_POSTINIT
+      { IOM_POSTINIT }
+    #endif
   }
 
   ~init ()
@@ -237,35 +247,57 @@ void io_manager::unreg (watcher &w, io_manager_vec<watcher> &queue)
 }
 
 #if IOM_TIME
-# ifdef IOM_LIBEVENT
-  void iom_time_c_callback (int fd, short events, void *data)
+  #ifdef IOM_LIBEVENT
+    void iom_time_c_callback (int fd, short events, void *data)
+    {
+      if (need_set_now) io_manager::set_now ();
+      time_watcher *w = static_cast<time_watcher *>(data);
+      w->call (*w);
+    }
+
+    void time_watcher::start ()
+    {
+      stop ();
+      evtimer_set (&ev, iom_time_c_callback, (void *)this);
+      struct timeval tv;
+      tv.tv_sec  = (long)at;
+      tv.tv_usec = (long)((at - (tstamp)tv.tv_sec) * 1000000.);
+      evtimer_add (&ev, &tv);
+      active = 1;
+    }
+  #else
+    void io_manager::reg   (time_watcher &w)  { io_manager::reg   (w, tw); }
+    void io_manager::unreg (time_watcher &w)  { io_manager::unreg (w, tw); }
+  #endif
+
+  void time_watcher::trigger ()
   {
-    time_watcher *w = static_cast<time_watcher *>(data);
-    w->call (*w);
+    call (*this);
+    start ();
   }
-# else
-  void io_manager::reg   (time_watcher &w)  { io_manager::reg   (w, tw); }
-  void io_manager::unreg (time_watcher &w)  { io_manager::unreg (w, tw); }
-# endif
-
-void time_watcher::trigger ()
-{
-  call (*this);
-  start ();
-}
 #endif
 
 #if IOM_IO
-# ifdef IOM_LIBEVENT
-  void iom_io_c_callback (int fd, short events, void *data)
-  {
-    io_watcher *w = static_cast<io_watcher *>(data);
-    w->call (*w, events);
-  }
-# else
-  void io_manager::reg   (io_watcher &w)    { io_manager::reg   (w, iow); }
-  void io_manager::unreg (io_watcher &w)    { io_manager::unreg (w, iow); }
-# endif
+  #ifdef IOM_LIBEVENT
+    void iom_io_c_callback (int fd, short events, void *data)
+    {
+      if (need_set_now) io_manager::set_now ();
+      io_watcher *w = static_cast<io_watcher *>(data);
+      w->call (*w, events);
+    }
+
+    void io_watcher::set (int fd_, short events_)
+    {
+      if (active) event_del (&ev);
+      fd = fd_;
+      events = events_;
+      event_set (&ev, fd_, events_ | EV_PERSIST, iom_io_c_callback, (void *)this);
+      if (active) event_add (&ev, 0);
+    }
+  #else
+    void io_manager::reg   (io_watcher &w)    { io_manager::reg   (w, iow); }
+    void io_manager::unreg (io_watcher &w)    { io_manager::unreg (w, iow); }
+  #endif
 #endif
 
 #if IOM_CHECK
@@ -408,8 +440,8 @@ void io_manager::loop ()
         }
       else
 #endif
-#ifndef IOM_LIBEVENT
         {
+          #ifndef IOM_LIBEVENT
           #if IOM_TIME
             // find earliest active watcher
             time_watcher *next = tw[0]; // the first time-watcher must exist at ALL times
@@ -426,135 +458,134 @@ void io_manager::loop ()
                 to = &tval;
               }
           #endif
+          #endif
         }
 
-#if IOM_IO || IOM_SIG
-      fd_set rfd, wfd;
-
-      FD_ZERO (&rfd);
-      FD_ZERO (&wfd);
-
-      int fds = 0;
-
-      #if IOM_IO
-        for (io_manager_vec<io_watcher>::const_iterator i = iow.end (); i-- > iow.begin (); )
-          if (*i)
-            {
-              if ((*i)->events & EVENT_READ ) FD_SET ((*i)->fd, &rfd);
-              if ((*i)->events & EVENT_WRITE) FD_SET ((*i)->fd, &wfd);
-
-              if ((*i)->fd >= fds) fds = (*i)->fd + 1;
-            }
-      #endif
+      #ifndef IOM_LIBEVENT
+        #if IOM_IO || IOM_SIG
+          fd_set rfd, wfd;
 
-      if (!to && !fds) //TODO: also check idle_watchers and check_watchers?
-        break; // no events
+          FD_ZERO (&rfd);
+          FD_ZERO (&wfd);
 
-      #if IOM_SIG
-        FD_SET (sigpipe[0], &rfd);
-        if (sigpipe[0] >= fds) fds = sigpipe[0] + 1;
-      #endif
+          int fds = 0;
 
-      #if IOM_SIG
-        // there is no race, as we use a pipe for signals, so select
-        // will return if a signal is caught.
-        sigprocmask (SIG_UNBLOCK, &sigs, NULL);
-      #endif
-      fds = select (fds, &rfd, &wfd, NULL, to);
-      #if IOM_SIG
-        sigprocmask (SIG_BLOCK, &sigs, NULL);
-      #endif
-
-#else
-      if (to)
-        event_loop (EVLOOP_NONBLOCK);
-      else
-        event_loop (EVLOOP_ONCE);
-#endif
+          #if IOM_IO
+            for (io_manager_vec<io_watcher>::const_iterator i = iow.end (); i-- > iow.begin (); )
+              if (*i)
+                {
+                  if ((*i)->events & EVENT_READ ) FD_SET ((*i)->fd, &rfd);
+                  if ((*i)->events & EVENT_WRITE) FD_SET ((*i)->fd, &wfd);
 
-      #if IOM_TIME
-        {
-          // update time, try to compensate for gross non-monotonic time changes
-          tstamp diff = NOW;
-          set_now ();
-          diff = NOW - diff;
+                  if ((*i)->fd >= fds) fds = (*i)->fd + 1;
+                }
+          #endif
 
-          if (diff < 0)
-            for (io_manager_vec<time_watcher>::const_iterator i = tw.end (); i-- > tw.begin (); )
-              if (*i)
-                (*i)->at += diff;
-        }
-      #endif
+          if (!to && !fds) //TODO: also check idle_watchers and check_watchers?
+            break; // no events
 
-#ifndef IOM_LIBEVENT
-      if (fds > 0)
-        {
           #if IOM_SIG
-            if (FD_ISSET (sigpipe[0], &rfd))
-              {
-                char ch;
-
-                while (read (sigpipe[0], &ch, 1) > 0)
-                  ;
-
-                for (vector<sig_vec *>::iterator svp = sw.end (); svp-- > sw.begin (); )
-                  if (*svp && (*svp)->pending)
-                    {
-                      sig_vec &sv = **svp;
-                      for (int i = sv.size (); i--; )
-                        if (!sv[i])
-                          sv.erase_unordered (i);
-                        else
-                          sv[i]->call (*sv[i]);
-
-                      sv.pending = false;
-                    }
-              }
+            FD_SET (sigpipe[0], &rfd);
+            if (sigpipe[0] >= fds) fds = sigpipe[0] + 1;
           #endif
 
-          #if IOM_IO
-            for (int i = iow.size (); i--; )
-              if (!iow[i])
-                iow.erase_unordered (i);
-              else
+          #if IOM_SIG
+            // there is no race, as we use a pipe for signals, so select
+            // will return if a signal is caught.
+            sigprocmask (SIG_UNBLOCK, &sigs, NULL);
+          #endif
+          fds = select (fds, &rfd, &wfd, NULL, to);
+          #if IOM_SIG
+            sigprocmask (SIG_BLOCK, &sigs, NULL);
+          #endif
+        #elif IOM_TIME
+          if (!to)
+            break;
+
+          select (0, 0, 0, 0, to);
+        #endif
+
+        #if IOM_TIME
+          {
+            // update time, try to compensate for gross non-monotonic time changes
+            tstamp diff = NOW;
+            set_now ();
+            diff = NOW - diff;
+
+            if (diff < 0)
+              for (io_manager_vec<time_watcher>::const_iterator i = tw.end (); i-- > tw.begin (); )
+                if (*i)
+                  (*i)->at += diff;
+          }
+        #endif
+
+        if (fds > 0)
+          {
+            #if IOM_SIG
+              if (FD_ISSET (sigpipe[0], &rfd))
                 {
-                  io_watcher &w = *iow[i];
-                  short revents = w.events;
+                  char ch;
+
+                  while (read (sigpipe[0], &ch, 1) > 0)
+                    ;
+
+                  for (vector<sig_vec *>::iterator svp = sw.end (); svp-- > sw.begin (); )
+                    if (*svp && (*svp)->pending)
+                      {
+                        sig_vec &sv = **svp;
+                        for (int i = sv.size (); i--; )
+                          if (!sv[i])
+                            sv.erase_unordered (i);
+                          else
+                            sv[i]->call (*sv[i]);
+
+                        sv.pending = false;
+                      }
+                }
+            #endif
 
-                  if (!FD_ISSET (w.fd, &rfd)) revents &= ~EVENT_READ;
-                  if (!FD_ISSET (w.fd, &wfd)) revents &= ~EVENT_WRITE;
+            #if IOM_IO
+              for (int i = iow.size (); i--; )
+                if (!iow[i])
+                  iow.erase_unordered (i);
+                else
+                  {
+                    io_watcher &w = *iow[i];
+                    short revents = w.events;
 
-                  if (revents)
-                    w.call (w, revents);
-                }
-          #endif
-        }
-      else if (fds < 0 && errno != EINTR)
-        {
-          perror ("io_manager: fatal error while waiting for I/O or time event, aborting.");
-          abort ();
-        }
-#else
-      if (0)
-        ;
-#endif
+                    if (!FD_ISSET (w.fd, &rfd)) revents &= ~EVENT_READ;
+                    if (!FD_ISSET (w.fd, &wfd)) revents &= ~EVENT_WRITE;
+
+                    if (revents)
+                      w.call (w, revents);
+                  }
+            #endif
+          }
+        else if (fds < 0 && errno != EINTR)
+          {
+            perror ("io_manager: fatal error while waiting for I/O or time event, aborting.");
+            abort ();
+          }
 #if IOM_IDLE
-      else
-        for (int i = iw.size (); i--; )
-          if (!iw[i])
-            iw.erase_unordered (i);
-          else
-            iw[i]->call (*iw[i]);
+        else
+          for (int i = iw.size (); i--; )
+            if (!iw[i])
+              iw.erase_unordered (i);
+            else
+              iw[i]->call (*iw[i]);
 #endif
 
-#elif IOM_TIME
-      if (!to)
-        break;
+      #else
+        need_set_now = true;
 
-      select (0, 0, 0, 0, to);
-      set_now ();
-      break;
-#endif
+        if (to)
+          event_loop (EVLOOP_NONBLOCK);
+        else
+          event_loop (EVLOOP_ONCE);
+
+        if (need_set_now) set_now ();
+      #endif
+        //TODO: IOM_IDLE
     }
 }
 
index e8f98a6d030bf429607c752d963e5504ec1a30b4..fdb8f4c6d96f75e96066794b70cfd35ee435b9eb 100644 (file)
--- a/src/iom.h
+++ b/src/iom.h
@@ -47,6 +47,11 @@ extern tstamp NOW;
 # include IOM_LIBEVENT
 # undef IOM_IO
 # define IOM_IO 1
+# undef IOM_TIME
+# define IOM_TIME 1
+# undef IOM_IDLE // NYI
+# undef IOM_SIG // NYI
+# undef IOM_CHILD // NYI
 #endif
 
 struct watcher;
@@ -141,11 +146,11 @@ void iom_io_c_callback (int fd, short events, void *data);
 struct io_watcher : watcher, callback<void (io_watcher &, short)> {
   struct event ev;
   int fd;
+  short events;
 
-  void set (int fd_, short events_) { fd = fd_; event_set (&ev, fd_, events_, iom_io_c_callback, (void *)this); }
-
+  void set (int fd_, short events_);
   void set (short events_) { set (fd, events_); }
-  void start () { event_add (&ev, 0); active = 1; }
+  void start () { if (!active) event_add (&ev, 0); active = 1; }
   void start (int fd_, short events_) { set (fd_, events_); start (); }
   void stop () { if (active) event_del (&ev); active = 0; }
 
@@ -188,25 +193,21 @@ struct time_watcher : watcher, callback<void (time_watcher &)> {
 
   void trigger ();
 
-  void set (tstamp when) { at = when; }
-  void operator () () { trigger (); }
-  void start ()
+  void set (tstamp when)
   {
-    struct timeval tv;
-    tv.tv_sec  = (long)at;
-    tv.tv_usec = (long)((at - (tstamp)tv.tv_sec) * 1000000.);
-    evtimer_add (&ev, &tv);
-    active = 1;
+    at = when;
+    if (active)
+      start ();
   }
-  void start (tstamp when) { set (when); start (); }
+  void operator () () { trigger (); }
+  void start ();
+  void start (tstamp when) { at = when; start (); }
   void stop () { if (active) evtimer_del (&ev); active = 0; }
 
   template<class O, class M>
   time_watcher (O object, M method)
   : callback<void (time_watcher &)> (object, method), at (0)
-  {
-    evtimer_set (&ev, iom_time_c_callback, (void *)this);
-  }
+  { }
   ~time_watcher () { stop (); }
 };
 #else