--- rxvt-unicode/src/iom.h 2004/02/09 07:11:49 1.10 +++ rxvt-unicode/src/iom.h 2007/10/25 12:42:00 1.31 @@ -1,8 +1,10 @@ /* - iom.h -- generic I/O multiplexor - Copyright (C) 2003, 2004 Marc Lehmann + iom.h -- generic I/O multiplexer + Copyright (C) 2003-2006 Marc Lehmann - This program is free software; you can redistribute it and/or modify + This file is part of GVPE. + + GVPE is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -13,8 +15,8 @@ GNU General Public License for more details. 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 + along with gvpe; if not, write to the Free Software + Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef IOM_H__ @@ -26,24 +28,32 @@ // edit iom_conf.h as appropriate. #include "iom_conf.h" -#include "callback.h" - -#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 +#if IOM_CHILD +# undef IOM_SIG +# define IOM_SIG 1 #endif +#include "callback.h" + typedef double tstamp; extern tstamp NOW; +// TSTAMP_MAX must still fit into a positive struct timeval +#define TSTAMP_MAX (double)(1UL<<31) + +//#define IOM_LIBEVENT "event.h" *NOT* a supported feature +#ifdef IOM_LIBEVENT +# include +# 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; #if IOM_IO struct io_watcher; @@ -57,124 +67,179 @@ #if IOM_IDLE struct idle_watcher; #endif +#if IOM_SIG +struct sig_watcher; +#endif +#if IOM_CHILD +struct child_watcher; +#endif template struct io_manager_vec : vector { -#if IOM_CHECK - bool activity; -#endif - void erase_unordered (unsigned int pos) { - watcher *w = (*this)[size () - 1]; - pop_back (); + watcher *w = (*this)[this->size () - 1]; + this->pop_back (); - if (size ()) - if ((*this)[pos] = w) + 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 { -#if IOM_IO - io_manager_vec iow; -#endif -#if IOM_CHECK - io_manager_vec cw; -#endif -#if IOM_TIME - io_manager_vec tw; -#endif -#if IOM_IDLE - io_manager_vec iw; -#endif - template - void reg (watcher *w, io_manager_vec &queue); + static void reg (watcher &w, io_manager_vec &queue); template - void unreg (watcher *w, io_manager_vec &queue); + static void unreg (watcher &w, io_manager_vec &queue); public: +#if IOM_TIME + // fetch time only + static tstamp now (); + + // set NOW + static void set_now (); +#endif + // register a watcher +#ifndef IOM_LIBEVENT #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_SIG + static void reg (sig_watcher &w); static void unreg (sig_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 #endif #if IOM_IDLE - void reg (idle_watcher *w); void unreg (idle_watcher *w); + static void reg (idle_watcher &w); static void unreg (idle_watcher &w); +#endif +#if IOM_CHILD + static void reg (child_watcher &w); static void unreg (child_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) { } + bool is_active () { return active; } + + watcher () : active (0) { } }; #if IOM_IO -enum { EVENT_READ = 1, EVENT_WRITE = 2 }; +#ifdef IOM_LIBEVENT +enum { EVENT_UNDEF = -1, EVENT_NONE = 0, EVENT_READ = EV_READ, EVENT_WRITE = EV_WRITE }; + +void iom_io_c_callback (int fd, short events, void *data); + +struct io_watcher : watcher, callback { + struct event ev; + int fd; + short events; + + void set (int fd_, short events_); + void set (short events_) { set (fd, events_); } + 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; } + + template + io_watcher (O object, M method) + : callback (object, method) + { } + ~io_watcher () { stop (); } +}; +#else +enum { EVENT_UNDEF = -1, EVENT_NONE = 0, EVENT_READ = 1, EVENT_WRITE = 2 }; -struct io_watcher : watcher, callback2 { +struct io_watcher : watcher, callback { int fd; short events; 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 - io_watcher (O1 *object, void (O2::*method)(io_watcher &, short)) - : callback2(object,method) + void start () { io_manager::reg (*this); } + void start (int fd_, short events_) { set (fd_, events_); start (); } + void stop () { io_manager::unreg (*this); } + + template + io_watcher (O object, M method) + : callback (object, method) { } ~io_watcher () { stop (); } }; #endif +#endif #if IOM_TIME -struct time_watcher : watcher, callback1 { +#ifdef IOM_LIBEVENT +void iom_time_c_callback (int fd, short events, void *data); + +struct time_watcher : watcher, callback { + struct event ev; + tstamp at; + + void trigger (); + + void set (tstamp when) + { + at = when; + if (active) + start (); + } + void operator () () { trigger (); } + void start (); + void start (tstamp when) { at = when; start (); } + void stop () { if (active) evtimer_del (&ev); active = 0; } + + template + time_watcher (O object, M method) + : callback (object, method), at (0) + { } + ~time_watcher () { stop (); } +}; +#else +struct time_watcher : watcher, callback { tstamp at; 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); } - - template - time_watcher (O1 *object, void (O2::*method)(time_watcher &)) - : callback1(object,method), at(0) + void operator () () { trigger (); } + void start () { io_manager::reg (*this); } + void start (tstamp when) { set (when); start (); } + void stop () { io_manager::unreg (*this); } + + template + time_watcher (O object, M method) + : callback (object, method), at (0) { } ~time_watcher () { stop (); } }; #endif +#endif #if IOM_CHECK // run before checking for new events -struct check_watcher : watcher, callback1 { - void start () { iom.reg (this); } - void stop () { iom.unreg (this); } - - template - check_watcher (O1 *object, void (O2::*method)(check_watcher &)) - : callback1(object,method) +struct check_watcher : watcher, callback { + void start () { io_manager::reg (*this); } + void stop () { io_manager::unreg (*this); } + + template + check_watcher (O object, M method) + : callback (object, method) { } ~check_watcher () { stop (); } }; @@ -182,17 +247,47 @@ #if IOM_IDLE // run after checking for any i/o, but before waiting -struct idle_watcher : watcher, callback1 { - void start () { iom.reg (this); } - void stop () { iom.unreg (this); } - - template - idle_watcher (O1 *object, void (O2::*method)(idle_watcher &)) - : callback1(object,method) +struct idle_watcher : watcher, callback { + void start () { io_manager::reg (*this); } + void stop () { io_manager::unreg (*this); } + + template + idle_watcher (O object, M method) + : callback (object, method) { } ~idle_watcher () { stop (); } }; #endif +#if IOM_SIG +struct sig_watcher : watcher, callback { + int signum; + + void start (int signum); + void stop () { io_manager::unreg (*this); } + + template + sig_watcher (O object, M method) + : callback (object, method), signum (0) + { } + ~sig_watcher () { stop (); } +}; +#endif + +#if IOM_CHILD +struct child_watcher : watcher, callback { + int /*pid_t*/ pid; + + void start (int pid) { this->pid = pid; io_manager::reg (*this); } + void stop () { io_manager::unreg (*this); } + + template + child_watcher (O object, M method) + : callback (object, method), pid (0) + { } + ~child_watcher () { stop (); } +}; +#endif + #endif