--- gvpe/src/iom.h 2003/03/21 21:21:02 1.3 +++ gvpe/src/iom.h 2004/01/17 14:08:57 1.16 @@ -1,5 +1,6 @@ /* - iom.h -- I/O multiplexor + iom.h -- generic I/O multiplexor + 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,34 +17,96 @@ 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 +// 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 +#include "callback.h" -#include "slog.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 +#endif typedef double tstamp; - extern tstamp NOW; -template class callback; +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 + +template +struct io_manager_vec : protected vector { + 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 { - vector pfs; - vector iow; - vector tw; // actually a heap -public: +#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); + + template + void unreg (watcher *w, io_manager_vec &queue); + +public: // register a watcher - void reg (int fd, short events, io_watcher *w); - void unreg (io_watcher *w); - void reg (time_watcher *w); - void unreg (time_watcher *w); +#if IOM_IO + void reg (io_watcher *w); void unreg (io_watcher *w); +#endif +#if IOM_TIME + void reg (time_watcher *w); void unreg (time_watcher *w); +#endif +#if IOM_CHECK + void reg (check_watcher *w); void unreg (check_watcher *w); +#endif +#if IOM_IDLE + void reg (idle_watcher *w); void unreg (idle_watcher *w); +#endif void loop (); @@ -51,84 +114,83 @@ ~io_manager (); }; -extern io_manager iom; +extern io_manager iom; // a singleton, together with it's construction/destruction problems. -template -class callback { - struct object { }; - - void *obj; - R (object::*meth)(A arg); - - // a proxy is a kind of recipe on how to call a specific class method - struct proxy_base { - virtual R call (void *obj, void (object::*meth)(A), A arg) = 0; - }; - template - struct proxy : proxy_base { - virtual R call (void *obj, void (object::*meth)(A), A arg) - { - ((reinterpret_cast(obj)) ->* (reinterpret_cast(meth))) - (arg); - } - }; +struct watcher { + int active; /* 0 == inactive, else index into respective vector */ - proxy_base *prxy; + watcher() : active(0) { } +}; + +#if IOM_IO +enum { EVENT_READ = 1, EVENT_WRITE = 2 }; + +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 () { iom.reg (this); } + void start (int fd_, short events_) { set (fd_, events_); iom.reg (this); } + void stop () { iom.unreg (this); } -public: template - callback (O1 *object, void (O2::*method)(A)) - { - static proxy p; - obj = reinterpret_cast(object); - meth = reinterpret_cast(method); - prxy = &p; - } - - R call(A arg) - { - return prxy->call (obj, meth, arg); - } - - void stop () - { - iom.unreg (this); - } + io_watcher (O1 *object, void (O2::*method)(io_watcher &, short)) + : callback2(object,method) + { } + ~io_watcher () { stop (); } }; +#endif -struct io_watcher : callback { - template - io_watcher (O1 *object, void (O2::*method)(short revents)) - : callback(object,method) - { } +#if IOM_TIME +struct time_watcher : watcher, callback1 { + tstamp at; - void start (int fd, short events) - { - iom.reg (fd, events, this); - } + 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) + { } + ~time_watcher () { stop (); } }; +#endif -struct time_watcher : callback { - tstamp at; +#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 - time_watcher (O1 *object, void (O2::*method)(tstamp &)) - : callback(object,method) - { } + check_watcher (O1 *object, void (O2::*method)(check_watcher &)) + : callback1(object,method) + { } + ~check_watcher () { stop (); } +}; +#endif - void set (tstamp when); +#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); } - void trigger () - { - call (at); - } - - void start (tstamp when = NOW) - { - set (when); - } + template + idle_watcher (O1 *object, void (O2::*method)(idle_watcher &)) + : callback1(object,method) + { } + ~idle_watcher () { stop (); } }; +#endif #endif