--- rxvt-unicode/src/iom.h 2003/11/24 17:28:08 1.1 +++ rxvt-unicode/src/iom.h 2007/10/25 10:44:14 1.30 @@ -1,8 +1,10 @@ /* - iom.h -- generic I/O multiplexor - Copyright (C) 2003 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,91 +15,278 @@ 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 VPE_IOM_H__ -#define VPE_IOM_H__ +#ifndef IOM_H__ +#define IOM_H__ -#include +// 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" + +#if IOM_CHILD +# undef IOM_SIG +# define IOM_SIG 1 +#endif -#include "rxvtvec.h" #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 +#endif + +struct watcher; +#if IOM_IO struct io_watcher; +#endif +#if IOM_TIME struct time_watcher; +#endif +#if IOM_CHECK +struct check_watcher; +#endif +#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 { + 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 { - simplevec iow; - simplevec tw; // actually a heap + template + static void reg (watcher &w, io_manager_vec &queue); + + template + static void unreg (watcher &w, io_manager_vec &queue); - void idle_cb (time_watcher &w); time_watcher *idle; public: +#if IOM_TIME + // fetch time only + static tstamp now (); + + // set NOW + static void set_now (); +#endif + // register a watcher - void reg (io_watcher *w); - void unreg (io_watcher *w); - void reg (time_watcher *w); - void unreg (time_watcher *w); +#ifndef IOM_LIBEVENT +#if IOM_IO + static void reg (io_watcher &w); static void unreg (io_watcher &w); +#endif +#if IOM_TIME + 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 + static void reg (check_watcher &w); static void unreg (check_watcher &w); +#endif +#endif +#if IOM_IDLE + 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 (); + static void loop (); +}; + +struct watcher { + int active; /* 0 == inactive, else index into respective vector */ + + bool is_active () { return active; } - io_manager (); - ~io_manager (); + watcher () : active (0) { } }; -extern io_manager iom; // a singleton, together with it's construction/destruction problems. +#if IOM_IO +#ifdef IOM_LIBEVENT +enum { EVENT_UNDEF = -1, EVENT_NONE = 0, EVENT_READ = EV_READ, EVENT_WRITE = EV_WRITE }; -enum { EVENT_READ = 1, EVENT_WRITE = 2 }; +void iom_io_c_callback (int fd, short events, void *data); -struct io_watcher : callback2 { +struct io_watcher : watcher, callback { + struct event ev; int fd; - short events; - template - io_watcher (O1 *object, void (O2::*method)(io_watcher &, short)) - : callback2(object,method) - { } + void set (int fd_, short events_) { fd = fd_; event_set (&ev, fd_, events_, iom_io_c_callback, (void *)this); } - ~io_watcher (); + void set (short events_) { set (fd, events_); } + void start () { 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 }; - void set(int fd_, short events_) { fd = fd_; events = events_; } +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 (int fd_, short events_) { set (fd_, events_); iom.reg (this); } - void stop () { iom.unreg (this); } + void set (short events_) { set (fd, events_); } + 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 -#define TSTAMP_CANCEL -1. +#if IOM_TIME +#ifdef IOM_LIBEVENT +void iom_time_c_callback (int fd, short events, void *data); -struct time_watcher : callback1 { +struct time_watcher : watcher, callback { + struct event ev; tstamp at; - template - time_watcher (O1 *object, void (O2::*method)(time_watcher &)) - : callback1(object,method) - { } + void trigger (); - ~time_watcher (); + void set (tstamp when) { at = when; } + void operator () () { trigger (); } + void start () + { + struct timeval tv; + tv.tv_sec = (long)at; + tv.tv_usec = (long)((at - (tstamp)tv.tv_sec) * 1000000.); + evtimer_add (&ev, &tv); + active = 1; + } + void start (tstamp when) { set (when); start (); } + void stop () { if (active) evtimer_del (&ev); active = 0; } + + template + time_watcher (O object, M method) + : callback (object, method), at (0) + { + evtimer_set (&ev, iom_time_c_callback, (void *)this); + } + ~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); } - - void reset (tstamp when = TSTAMP_CANCEL) - { - stop (); - at = when; - } + 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, 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 (); } +}; +#endif + +#if IOM_IDLE +// run after checking for any i/o, but before waiting +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