--- gvpe/src/iom.h 2003/04/04 05:26:45 1.11 +++ gvpe/src/iom.h 2004/11/12 12:49:12 1.25 @@ -1,5 +1,6 @@ /* - iom.h -- I/O multiplexor + iom.h -- generic I/O multiplexer + Copyright (C) 2003, 2004 Marc Lehmann 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 @@ -16,126 +17,185 @@ Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef VPE_IOM_H__ -#define VPE_IOM_H__ +#ifndef IOM_H__ +#define IOM_H__ -#include - -#include - -#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" #include "callback.h" -#include "slog.h" -typedef double tstamp; +#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 +typedef double tstamp; extern tstamp NOW; +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 -class io_manager { - vector pfs; - vector iow; - vector tw; // actually a heap +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; + } +}; - void idle_cb (time_watcher &w); time_watcher *idle; -public: +// only used as a namespace, and for initialisation purposes +class io_manager { + template + static void reg (watcher &w, io_manager_vec &queue); - void reschedule_time_watchers (); + template + static void unreg (watcher &w, io_manager_vec &queue); +public: // register a watcher - void reg (io_watcher *w); - void unreg (io_watcher *w); - void reg (time_watcher *w); - void unreg (time_watcher *w); +#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_CHECK + 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 (); + static void loop (); +}; + +struct watcher { + int active; /* 0 == inactive, else index into respective vector */ - io_manager (); - ~io_manager (); + watcher () : active (0) { } }; -extern io_manager iom; // a singleton, together with it's construction/destruction problems. +#if IOM_IO +enum { EVENT_READ = 1, EVENT_WRITE = 2 }; -struct io_watcher : callback2 { - pollfd *p; +struct io_watcher : watcher, callback2 { + int fd; + short 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); } template - io_watcher (O1 *object, void (O2::*method)(io_watcher &, short)) - : callback2(object,method) - { } + io_watcher (O1 *object, void (O2::*method) (io_watcher &, short)) + : callback2 (object,method) + { } + ~io_watcher () { stop (); } +}; +#endif - ~io_watcher (); +#if IOM_TIME +struct time_watcher : watcher, callback1 { + tstamp at; + + void trigger (); - void set(int fd, short events) - { - assert (p); - p->fd = fd; - p->events = events; - } - - void set(short events) - { - assert (p); - p->events = events; - } - - void start (int fd, short events) - { - iom.reg (this); // make sure pfd is set - - p->fd = fd; - p->events = events; - } - - void stop () - { - iom.unreg (this); - } + void set (tstamp when) { 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 + time_watcher (O1 *object, void (O2::*method) (time_watcher &)) + : callback1 (object,method), at (0) + { } + ~time_watcher () { stop (); } }; +#endif -#define TSTAMP_CANCEL -1. +#if IOM_CHECK +// run before checking for new events +struct check_watcher : watcher, callback1 { + void start () { io_manager::reg (*this); } + void stop () { io_manager::unreg (*this); } -struct time_watcher : callback1 { - bool registered; // already registered? - tstamp at; + template + check_watcher (O1 *object, void (O2::*method) (check_watcher &)) + : callback1 (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 start () { io_manager::reg (*this); } + void stop () { io_manager::unreg (*this); } template - time_watcher (O1 *object, void (O2::*method)(time_watcher &)) - : callback1(object,method) - , registered(false) + idle_watcher (O1 *object, void (O2::*method) (idle_watcher &)) + : callback1 (object,method) { } + ~idle_watcher () { stop (); } +}; +#endif - ~time_watcher (); - - void set (tstamp when); - void trigger (); +#if IOM_SIG +struct sig_watcher : watcher, callback1 { + int signum; - void operator ()() - { - trigger (); - } - - void start (); - void start (tstamp when) - { - set (when); - } - - void stop () - { - iom.unreg (this); - } - - void reset (tstamp when = TSTAMP_CANCEL) - { - stop (); + void start (int signum); + void stop () { io_manager::unreg (*this); } - at = when; - } + template + sig_watcher (O1 *object, void (O2::*method) (sig_watcher &)) + : callback1 (object,method), signum (-1) + { } + ~sig_watcher () { stop (); } }; +#endif #endif