*** empty log message ***
authorpcg <pcg>
Fri, 16 Jan 2004 22:11:09 +0000 (22:11 +0000)
committerpcg <pcg>
Fri, 16 Jan 2004 22:11:09 +0000 (22:11 +0000)
Changes
src/Makefile.in
src/command.C
src/iom.C
src/iom.h
src/rxvtd.C
src/screen.C

diff --git a/Changes b/Changes
index 12d08c26f3589ca546818c354dd99d90ceca8f9e..1d33b770050e2520175a8f0c6dc58e4321dbc696 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,6 +1,7 @@
-1.4
+1.4  Fri Jan 16 23:03:22 CET 2004
        - fix stupid segfault on esc-c.
         - small font tunings.
+        - much better io manager, less bugs, higher speed.
 
 1.3  2003-12-26
         - fix a bug in font height selection
index b9df2cafd93bc6d739d31beda6b003a08c0cb240..e9c548ab7cd6f201c83726f1afad643d9d3aead0 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: Makefile.in,v 1.6 2003-12-18 00:56:51 pcg Exp $
+# $Id: Makefile.in,v 1.7 2004-01-16 22:11:09 pcg Exp $
 @MCOMMON@
 
 LINT = lint -DNARROWPROTO=1 $(XINC) -chapbxz
@@ -12,7 +12,7 @@ basedir = ..
 thisdir = src
 MKDIR = @top_srcdir@/autoconf/mkinstalldirs
 
-SUPLIB = -lsupc++
+SUPLIB = -fno-exceptions -lsupc++ # TODO: only for g++
 
 # for developers: the following debug options may be used
 #      -DDEBUG_CMD -DDEBUG_MAIN -DDEBUG_MENU -DDEBUG_MENUARROWS
index 64ea80f498ce252516e1a94635f311a916826a73..0fbbde0ac8419d19ee90a13ea92b1d69928f38a3 100644 (file)
@@ -1,7 +1,7 @@
 /*--------------------------------*-C-*---------------------------------*
  * File:       command.c
  *----------------------------------------------------------------------*
- * $Id: command.C,v 1.27 2003-12-30 01:35:58 pcg Exp $
+ * $Id: command.C,v 1.28 2004-01-16 22:11:09 pcg Exp $
  *
  * All portions of code are copyright by their respective author/s.
  * Copyright (c) 1992      John Bovey, University of Kent at Canterbury <jdb@ukc.ac.uk>
@@ -758,9 +758,10 @@ rxvt_term::process_x_events ()
 void
 rxvt_term::blink_cb (time_watcher &w)
 {
-  w.at += BLINK_INTERVAL;
   hidden_cursor = !hidden_cursor;
   want_refresh = 1;
+
+  w.start (w.at + BLINK_INTERVAL);
 }
 #endif
 
@@ -1039,8 +1040,6 @@ rxvt_term::pointer_unblank ()
 void
 rxvt_term::pointer_blank ()
 {
-  pointer_ev.stop ();
-
   if (!(Options & Opt_pointerBlank))
     return;
 
index fd2b248ccf90e25aa882cd8b47daa4a1283ccc29..812b7aae8473c3c111700a9d4c6156340f78f743 100644 (file)
--- a/src/iom.C
+++ b/src/iom.C
 #include "../config.h"
 
 #include <cstdio>
+#include <cstdlib>
+#include <cerrno>
 
 #include <sys/select.h>
 #include <sys/time.h>
 
 #include "iom.h"
 
+// TSTAMP_MAX must still fit into a positive struct timeval
+#define TSTAMP_MAX (double)(1UL<<31)
+
 tstamp NOW;
-bool iom_valid;
+static bool iom_valid;
 io_manager iom;
 
 template<class watcher>
 void io_manager::reg (watcher *w, simplevec<watcher *> &queue)
 {
-  if (find (queue.begin (), queue.end (), w) == queue.end ())
-    queue.push_back (w);
+  if (!iom_valid)
+    abort ();
+
+  if (!w->active)
+    {
+      queue.push_back (w);
+      w->active = queue.size ();
+    }
 }
 
 template<class watcher>
 void io_manager::unreg (watcher *w, simplevec<watcher *> &queue)
 {
-  queue.erase (find (queue.begin (), queue.end (), w));
-}
-
-#if IOM_IO
-io_watcher::~io_watcher ()
-{
-  if (iom_valid)
-    iom.unreg (this);
-}
-
-void io_manager::reg (io_watcher *w)
-{
-  reg (w, iow);
-}
+  if (!iom_valid)
+    return;
 
-void io_manager::unreg (io_watcher *w)
-{
-  unreg (w, iow);
+  if (w->active)
+    {
+      queue [w->active - 1] = 0;
+      w->active = 0;
+    }
 }
 
-#endif
-
 #if IOM_TIME
 void time_watcher::trigger ()
 {
@@ -70,59 +69,23 @@ void time_watcher::trigger ()
   iom.reg (this);
 }
 
-time_watcher::~time_watcher ()
-{
-  if (iom_valid)
-    iom.unreg (this);
-
-  at = TSTAMP_CANCEL;
-}
-
-void io_manager::reg (time_watcher *w)
-{
-  reg (w, tw);
-}
+void io_manager::reg (time_watcher *w) { reg (w, tw); }
+void io_manager::unreg (time_watcher *w) { unreg (w, tw); }
+#endif
 
-void io_manager::unreg (time_watcher *w)
-{
-  unreg (w, tw);
-}
+#if IOM_IO
+void io_manager::reg (io_watcher *w) { reg (w, iow); } 
+void io_manager::unreg (io_watcher *w) { unreg (w, iow); }
 #endif
 
 #if IOM_CHECK
-check_watcher::~check_watcher ()
-{
-  if (iom_valid)
-    iom.unreg (this);
-}
-
-void io_manager::reg (check_watcher *w)
-{
-  reg (w, cw);
-}
-
-void io_manager::unreg (check_watcher *w)
-{
-  unreg (w, cw);
-}
+void io_manager::reg (check_watcher *w) { reg (w, cw); }
+void io_manager::unreg (check_watcher *w) { unreg (w, cw); }
 #endif
 
 #if IOM_IDLE
-idle_watcher::~idle_watcher ()
-{
-  if (iom_valid)
-    iom.unreg (this);
-}
-
-void io_manager::reg (idle_watcher *w)
-{
-  reg (w, iw);
-}
-
-void io_manager::unreg (idle_watcher *w)
-{
-  unreg (w, iw);
-}
+void io_manager::reg (idle_watcher *w) { reg (w, iw); }
+void io_manager::unreg (idle_watcher *w) { unreg (w, iw); }
 #endif
 
 #if IOM_TIME
@@ -158,78 +121,97 @@ void io_manager::loop ()
 #endif
         {
 #if IOM_TIME
-          time_watcher *w;
+          time_watcher *next;
 
-          for (;tw.size ();)
+          for (;;)
             {
-              w = tw[0];
+              next = tw[0]; // the first time-watcher must exist at ALL times
 
-              for (time_watcher **i = tw.begin (); i < tw.end (); ++i)
-                if ((*i)->at < w->at)
-                  w = *i;
+              for (int i = tw.size (); i--; )
+                if (!tw[i])
+                  tw.erase_unordered (i);
+                else if (tw[i]->at < next->at)
+                  next = tw[i];
 
-              if (w->at > NOW)
+              if (next->at > NOW)
                 {
-                  double diff = w->at - NOW;
-                  tval.tv_sec  = (int)diff;
-                  tval.tv_usec = (int)((diff - tval.tv_sec) * 1000000);
-                  to = &tval;
+                  if (next != tw[0])
+                    {
+                      double diff = next->at - NOW;
+                      tval.tv_sec  = (int)diff;
+                      tval.tv_usec = (int)((diff - tval.tv_sec) * 1000000);
+                      to = &tval;
+                    }
                   break;
                 }
-              else if (w->at >= 0)
-                w->call (*w);
-              else
-                unreg (w);
+              else if (next->at >= 0)
+                {
+                  unreg (next);
+                  next->call (*next);
+                }
             }
 #endif
         }
 
 #if IOM_CHECK
-      for (int i = 0; i < cw.size (); ++i)
-        cw[i]->call (*cw[i]);
+      for (int i = cw.size (); i--; )
+        if (!cw[i])
+          cw.erase_unordered (i);
+        else
+          cw[i]->call (*cw[i]);
 #endif
 
 #if IOM_IO
-      fd_set rfd, wfd;
+      fd_set rfd, wfd, efd;
 
       FD_ZERO (&rfd);
       FD_ZERO (&wfd);
 
       int fds = 0;
 
-      for (io_watcher **w = iow.begin (); w < iow.end (); ++w)
-        {
-          if ((*w)->events & EVENT_READ ) FD_SET ((*w)->fd, &rfd);
-          if ((*w)->events & EVENT_WRITE) FD_SET ((*w)->fd, &wfd);
+      for (io_watcher **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 ((*w)->fd >= fds) fds = (*w)->fd + 1;
-        }
+            if ((*i)->fd >= fds) fds = (*i)->fd + 1;
+          }
 
-      if (!to && !fds)
+      if (!to && !fds) //TODO: also check idle_watchers and check_watchers
         break; // no events
 
-      fds = select (fds, &rfd, &wfd, 0, to);
+      fds = select (fds, &rfd, &wfd, &efd, to);
 # if IOM_TIME
       set_now ();
 # endif
 
       if (fds > 0)
-        for (int i = 0; i < iow.size (); ++i)
-          {
-            io_watcher *w = iow[i];
-
-            short revents = w->events;
+        for (int i = iow.size (); i--; )
+          if (!iow[i])
+            iow.erase_unordered (i);
+          else
+            {
+              short revents = iow[i]->events;
 
-            if (!FD_ISSET (w->fd, &rfd)) revents &= ~EVENT_READ;
-            if (!FD_ISSET (w->fd, &wfd)) revents &= ~EVENT_WRITE;
+              if (!FD_ISSET (iow[i]->fd, &rfd)) revents &= ~EVENT_READ;
+              if (!FD_ISSET (iow[i]->fd, &wfd)) revents &= ~EVENT_WRITE;
 
-            if (revents)
-              w->call (*w, revents);
-          }
+              if (revents)
+                iow[i]->call (*iow[i], revents);
+            }
+      else if (fds < 0 && errno != EINTR)
+        {
+          perror ("Error while waiting for I/O or time event");
+          abort ();
+        }
 #if IOM_IDLE
-      else if (iw.size ())
-        for (int i = 0; i < iw.size (); ++i)
-          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
@@ -244,13 +226,31 @@ void io_manager::loop ()
     }
 }
 
+// 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
+static struct tw0 : time_watcher {
+  void cb (time_watcher &w)
+  {
+    // should never get called
+    // reached end-of-time, or tstamp has a bogus definition :)
+    abort ();
+  }
+
+  tw0()
+  : time_watcher (this, &tw0::cb)
+  { }
+} tw0;
+
 io_manager::io_manager ()
 {
+  iom_valid = true;
+
 #if IOM_TIME
   set_now ();
-#endif
 
-  iom_valid = true;
+  tw0.start (TSTAMP_MAX);
+#endif
 }
 
 io_manager::~io_manager ()
index 6912a6a3b29857d0c3644a5b25855cab826e0ab5..470791bcfaed4a1c5b0eb468aae6811225620983 100644 (file)
--- a/src/iom.h
+++ b/src/iom.h
 
 #include <cassert>
 
-#include "rxvtvec.h"
 #include "callback.h"
+#include "rxvtvec.h"
+
+#ifndef IOM_IO
+# define IOM_IO 1
+#endif
+#ifndef IOM_TIME
+# define IOM_TIME 1
+#endif
+#ifndef IOM_CHECK
+# define IOM_CHECK 1
+#endif
+#ifndef IOM_IDLE
+# define IOM_IDLE 0
+#endif
 
-#define IOM_IO 1
-#define IOM_TIME 1
-#define IOM_CHECK 1
-#define IOM_IDLE 0
+typedef double tstamp;
+extern tstamp NOW;
 
 #if IOM_IO
-  typedef double tstamp;
-  extern tstamp NOW;
-
   struct io_watcher;
 #endif
 #if IOM_TIME
   struct idle_watcher;
 #endif
 
+template<class watcher>
+struct io_manager_vec : protected simplevec<watcher *> {
+  friend class io_manager;
+protected:
+  void erase_unordered (unsigned int pos)
+  {
+    watcher *w = (*this)[size () - 1];
+    pop_back ();
+
+    if (size ())
+      if ((*this)[pos] = w)
+        w->active = pos + 1;
+  }
+};
+
 class io_manager {
 #if IOM_IO
-  simplevec<io_watcher *>    iow;
+  io_manager_vec<io_watcher>    iow;
 #endif
 #if IOM_CHECK
-  simplevec<check_watcher *> cw;
+  io_manager_vec<check_watcher> cw;
 #endif
 #if IOM_TIME
-  simplevec<time_watcher *>  tw;
+  io_manager_vec<time_watcher>  tw;
 #endif
 #if IOM_IDLE
-  simplevec<idle_watcher *>  iw;
+  io_manager_vec<idle_watcher>  iw;
 #endif
 
   template<class watcher>
@@ -89,42 +112,38 @@ public:
 
 extern io_manager iom; // a singleton, together with it's construction/destruction problems.
 
+struct watcher {
+  int active; /* 0 == inactive, else index into respective vector */
+
+  watcher() : active(0) { }
+};
+
 #if IOM_IO
 enum { EVENT_READ = 1, EVENT_WRITE = 2 };
 
-struct io_watcher : callback2<void, io_watcher &, short> {
+struct io_watcher : watcher, callback2<void, io_watcher &, short> {
   int fd;
   short events;
 
-  template<class O1, class O2>
-  io_watcher (O1 *object, void (O2::*method)(io_watcher &, short))
-    : callback2<void, io_watcher &, short>(object,method)
-    { }
-
-  ~io_watcher ();
-
   void set (int fd_, short events_) { fd = fd_; events = events_; }
 
   void set (short events_) { set (fd, events_); }
   void start () { iom.reg (this); }
   void start (int fd_, short events_) { set (fd_, events_); iom.reg (this); }
   void stop () { iom.unreg (this); }
+
+  template<class O1, class O2>
+  io_watcher (O1 *object, void (O2::*method)(io_watcher &, short))
+  : callback2<void, io_watcher &, short>(object,method)
+  { }
+  ~io_watcher () { stop (); }
 };
 #endif
 
 #if IOM_TIME
-enum { TSTAMP_CANCEL = -1 };
-
-struct time_watcher : callback1<void, time_watcher &> {
+struct time_watcher : watcher, callback1<void, time_watcher &> {
   tstamp at;
 
-  template<class O1, class O2>
-  time_watcher (O1 *object, void (O2::*method)(time_watcher &))
-    : callback1<void, time_watcher &>(object,method)
-    { }
-
-  ~time_watcher ();
-
   void trigger ();
 
   void set (tstamp when) { at = when; }
@@ -133,41 +152,39 @@ struct time_watcher : callback1<void, time_watcher &> {
   void start (tstamp when) { set (when); iom.reg (this); }
   void stop () { iom.unreg (this); }
 
-  void reset (tstamp when = TSTAMP_CANCEL)
-    {
-      stop ();
-      at = when;
-    }
+  template<class O1, class O2>
+  time_watcher (O1 *object, void (O2::*method)(time_watcher &))
+  : callback1<void, time_watcher &>(object,method)
+  { }
+  ~time_watcher () { stop (); }
 };
 #endif
 
 #if IOM_CHECK
 // run before checking for new events
-struct check_watcher : callback1<void, check_watcher &> {
-  template<class O1, class O2>
-  check_watcher (O1 *object, void (O2::*method)(check_watcher &))
-    : callback1<void, check_watcher &>(object,method)
-    { }
-
-  ~check_watcher ();
-
+struct check_watcher : watcher, callback1<void, check_watcher &> {
   void start () { iom.reg (this); }
   void stop () { iom.unreg (this); }
+
+  template<class O1, class O2>
+  check_watcher (O1 *object, void (O2::*method)(check_watcher &))
+  : callback1<void, check_watcher &>(object,method)
+  { }
+  ~check_watcher () { stop (); }
 };
 #endif
 
 #if IOM_IDLE
 // run after checking for any i/o, but before waiting
-struct idle_watcher : callback1<void, idle_watcher &> {
+struct idle_watcher : watcher, callback1<void, idle_watcher &> {
+  void start () { iom.reg (this); }
+  void stop () { iom.unreg (this); }
+
   template<class O1, class O2>
   idle_watcher (O1 *object, void (O2::*method)(idle_watcher &))
     : callback1<void, idle_watcher &>(object,method)
     { }
-
-  ~idle_watcher ();
-
-  void start () { iom.reg (this); }
-  void stop () { iom.unreg (this); }
+  ~idle_watcher () { stop (); }
 };
 #endif
 
index 52a1aa7ec617d96b2341d86add4a09de7836cd8f..dd7af9464639da987feebdec99afa93e8344cccd 100644 (file)
@@ -171,3 +171,4 @@ main(int argc, const char *const *argv)
 #endif
   return EXIT_SUCCESS;
 }
+
index c3bba00ac29ee295d2baf9546ba6654904d41bcc..ea9f139a0a5ddad98dc7fb0fb0983b7adefa43a4 100644 (file)
@@ -1,7 +1,7 @@
 /*--------------------------------*-C-*--------------------------------------*
  * File:        screen.c
  *---------------------------------------------------------------------------*
- * $Id: screen.C,v 1.15 2004-01-16 16:34:56 pcg Exp $
+ * $Id: screen.C,v 1.16 2004-01-16 22:11:09 pcg Exp $
  *
  * Copyright (c) 1997-2001 Geoff Wing <gcw@pobox.com>
  *
@@ -2567,10 +2567,9 @@ rxvt_selection_paste(pR_ Window win, Atom prop, Bool delete_prop)
 void
 rxvt_term::incr_cb (time_watcher &w)
 {
-  w.stop ();
   selection_wait = Sel_none;
 
-  rxvt_print_error("data loss: timeout on INCR selection paste");
+  rxvt_print_error ("data loss: timeout on INCR selection paste");
 }
 
 /*