*** empty log message ***
[dana/urxvt.git] / src / iom.h
index ec381a8..5b133a6 100644 (file)
--- a/src/iom.h
+++ b/src/iom.h
@@ -1,6 +1,6 @@
 /*
-    iom.h -- generic I/O multiplexor
-    Copyright (C) 2003 Marc Lehmann <pcg@goof.com>
+    iom.h -- generic I/O multiplexer
+    Copyright (C) 2003, 2004 Marc Lehmann <pcg@goof.com>
  
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
  
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
-    Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
-#ifndef VPE_IOM_H__
-#define VPE_IOM_H__
+#ifndef IOM_H__
+#define IOM_H__
 
-#include <cassert>
+// required:
+// - a vector template like simplevec or stl's vector
+// - defines for all watcher types required in your app
+// edit iom_conf.h as appropriate.
+#include "iom_conf.h"
 
-#include "rxvtvec.h"
 #include "callback.h"
 
-#define IOM_IO 1
-#define IOM_TIME 1
-#undef IOM_CHECK
+#ifndef IOM_IO
+# define IOM_IO 0
+#endif
+#ifndef IOM_TIME
+# define IOM_TIME 0
+#endif
+#ifndef IOM_CHECK
+# define IOM_CHECK 0
+#endif
+#ifndef IOM_IDLE
+# define IOM_IDLE 0
+#endif
+#ifndef IOM_SIG
+# define IOM_SIG 0
+#endif
 
-#if IOM_IO
-  typedef double tstamp;
-  extern tstamp NOW;
+typedef double tstamp;
+extern tstamp NOW;
 
-  struct io_watcher;
+struct watcher;
+#if IOM_IO
+struct io_watcher;
 #endif
 #if IOM_TIME
-  struct time_watcher;
+struct time_watcher;
 #endif
 #if IOM_CHECK
-  struct check_watcher;
+struct check_watcher;
 #endif
-
-class io_manager {
-#if IOM_IO
-  simplevec<io_watcher *>    iow;
+#if IOM_IDLE
+struct idle_watcher;
 #endif
-#if IOM_CHECK
-  simplevec<check_watcher *> cw;
+#if IOM_SIG
+struct sig_watcher;
 #endif
-#if IOM_TIME
-  simplevec<time_watcher *>  tw;
 
-  void idle_cb (time_watcher &w); time_watcher *idle;
-#endif
+template<class watcher>
+struct io_manager_vec : vector<watcher *> {
+  void erase_unordered (unsigned int pos)
+  {
+    watcher *w = (*this)[this->size () - 1];
+    this->pop_back ();
+
+    if (!this->empty ())
+      if (((*this)[pos] = w)) // '=' is correct!
+        w->active = pos + 1;
+  }
+};
 
+// only used as a namespace, and for initialisation purposes
+class io_manager {
   template<class watcher>
-  void reg (watcher *w, simplevec<watcher *> &queue);
+  static void reg (watcher &w, io_manager_vec<watcher> &queue);
 
   template<class watcher>
-  void unreg (watcher *w, simplevec<watcher *> &queue);
+  static void unreg (watcher &w, io_manager_vec<watcher> &queue);
 
 public:
+#if IOM_TIME
+  // fetch time only
+  static tstamp now ();
+
+  // set NOW
+  static void set_now ();
+#endif
+
   // register a watcher
 #if IOM_IO
-  void reg (io_watcher   *w);  void unreg (io_watcher   *w);
+  static void reg (io_watcher    &w); static void unreg (io_watcher    &w);
 #endif
 #if IOM_TIME
-  void reg (time_watcher *w);  void unreg (time_watcher *w);
+  static void reg (time_watcher  &w); static void unreg (time_watcher  &w);
 #endif
 #if IOM_CHECK
-  void reg (check_watcher *w); void unreg (check_watcher *w);
+  static void reg (check_watcher &w); static void unreg (check_watcher &w);
+#endif
+#if IOM_IDLE
+  static void reg (idle_watcher  &w); static void unreg (idle_watcher  &w);
+#endif
+#if IOM_SIG
+  static void reg (sig_watcher   &w); static void unreg (sig_watcher   &w);
 #endif
   
-  void loop ();
-
-  io_manager ();
-  ~io_manager ();
+  static void loop ();
 };
 
-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(int fd_, short events_) { fd = fd_; events = events_; }
+  void set (short events_) { set (fd, events_); }
+  void start () { io_manager::reg (*this); }
+  void start (int fd_, short events_) { set (fd_, events_); io_manager::reg (*this); }
+  void stop () { io_manager::unreg (*this); }
 
-  void set(short events_) { set (fd, events_); }
-  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; }
-  void operator ()() { trigger (); }
-  void start () { iom.reg (this); }
-  void start (tstamp when) { set (when); iom.reg (this); }
-  void stop () { iom.unreg (this); }
-
-  void reset (tstamp when = TSTAMP_CANCEL)
-    {
-      stop ();
-      at = when;
-    }
+  void operator () () { trigger (); }
+  void start () { io_manager::reg (*this); }
+  void start (tstamp when) { set (when); io_manager::reg (*this); }
+  void stop () { io_manager::unreg (*this); }
+
+  template<class O1, class O2>
+  time_watcher (O1 *object, void (O2::*method) (time_watcher &))
+  : callback1<void, time_watcher &> (object,method), at (0)
+  { }
+  ~time_watcher () { stop (); }
 };
 #endif
 
 #if IOM_CHECK
 // run before checking for new events
-struct check_watcher : callback1<void, check_watcher &> {
+struct check_watcher : watcher, callback1<void, check_watcher &> {
+  void start () { io_manager::reg (*this); }
+  void stop () { io_manager::unreg (*this); }
+
   template<class O1, class O2>
-  check_watcher (O1 *object, void (O2::*method)(check_watcher &))
-    : callback1<void, check_watcher &>(object,method)
+  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 : watcher, callback1<void, idle_watcher &> {
+  void start () { io_manager::reg (*this); }
+  void stop () { io_manager::unreg (*this); }
+
+  template<class O1, class O2>
+  idle_watcher (O1 *object, void (O2::*method) (idle_watcher &))
+    : callback1<void, idle_watcher &> (object,method)
     { }
+  ~idle_watcher () { stop (); }
+};
+#endif
 
-  ~check_watcher ();
+#if IOM_SIG
+struct sig_watcher : watcher, callback1<void, sig_watcher &> {
+  int signum;
 
-  void start () { iom.reg (this); }
-  void stop () { iom.unreg (this); }
+  void start (int signum);
+  void stop () { io_manager::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