diff options
Diffstat (limited to 'mcop/iomanager.h')
-rw-r--r-- | mcop/iomanager.h | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/mcop/iomanager.h b/mcop/iomanager.h new file mode 100644 index 0000000..a226e0c --- /dev/null +++ b/mcop/iomanager.h @@ -0,0 +1,214 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +/* + * BC - Status (2002-03-08): + * BINARY COMPATIBLE: IONotify, TimeNotify, IOManager + * NO BC FOR: StdIOManager + * + * Whereas the first three are part of the Interface (i.e. DEFINITELY to be + * kept binary compatible), the next three are part of the implementation + * in libmcop and subject to any kind of change. + */ + +#ifndef IOMANAGER_H +#define IOMANAGER_H + +#include <sys/time.h> +#include <sys/types.h> +#include <unistd.h> +#include <list> +#include <stack> + +#include "arts_export.h" + +namespace Arts { +// constants: + +/** + * What does the reentrant flag do? + * + * The IOManager offers a processOneEvent call. This means, that you can ask + * that I/O is handled, even while in a routine that handles I/O. As a + * practical example: you may have got a remote invocation for the function + * foo. Now you are in function foo() and call function bar() on a remote + * server. When you wait for the result, you obviously will again require + * the IOManager to wait for it. Thus this is a case where you need reentrant + * I/O handling. + * + * That way, you get a multiple level stack: + * + * <pre> + * [...] + * | + * [ Hander for I/O ] + * | + * [ IOManager ] level 2 + * | + * [ Some other function ] + * | + * [ Hander for I/O ] + * | + * [ IOManager ] level 1 + * | + * [ main() ] + * </pre> + * + * What reentrant does, is to allow that IO Watch to be activated at levels + * higher than one. + * + * Timers and notifications, on the other hand will only be carried out at + * level 1. + */ +struct IOType { + enum { read = 1, write = 2, except = 4, reentrant = 8, all = 15 }; +}; + +/** + * IONotify is the base class you can derive from to receive callbacks about + * IO activity. You will need to call the watchFD function of the IOManager + * to start watching a filedescriptor. + * + * @see Arts::IOManager + */ +class ARTS_EXPORT IONotify { +public: + /** + * This is the function that gets called if something relevant happened + * on the filedescriptor you watched with IOManager::watchFD. + * + * @param fd is the filedescriptor that has seen some IO activity + * @param type is the type of activity (as combination of IOType) + */ + virtual void notifyIO(int fd, int type) = 0; +}; + +/** + * TimeNotify is the base class you can derive from to receive timer callbacks. + * You will need to call the addTimer function of the IOManager to start + * watching a filedescriptor. + * + * @see Arts::IOManager + */ +class ARTS_EXPORT TimeNotify { +public: + /** + * This function gets whenever the timer is activated. Note that the + * IOManager will try to "catch up" lost time, that is, if you have a + * 300ms timer that didn't get called for a second (because there was + * something else to do), you'll receive three calls in a row. + */ + virtual void notifyTime() = 0; +}; + +/** + * Provides services like timers and notifications when filedescriptors get + * ready to read/write. + */ +class ARTS_EXPORT IOManager { +public: + virtual ~IOManager() {}; + + /** + * processes exactly one io event + */ + virtual void processOneEvent(bool blocking) = 0; + + /** + * enters a loop which processes io events, until terminate is called + * + * may only be called once (use processOneEvent for other purposes) + */ + virtual void run() = 0; + + /** + * terminates the io event loop (which was started with run) + */ + virtual void terminate() = 0; + + /** + * starts watching one filedescriptor for certain types of operations + * + * notifies the notify object when e.g. the fd requires (allows) reading + * and types contained IOType::read. + * + * @see Arts::IOType + * @see Arts::IONotify + */ + virtual void watchFD(int fd, int types, IONotify *notify) = 0; + + /** + * stops watching a filedescriptor + */ + virtual void remove(IONotify *notify, int types) = 0; + /* + * BCI when breaking BC, probably int fd should be added as argument + * to remove, this would be more consistent with the way watches are added + */ + + /** + * starts a periodic timer + * + * @see Arts::TimeNotify + */ + virtual void addTimer(int milliseconds, TimeNotify *notify) = 0; + + /** + * stops the timer + */ + virtual void removeTimer(TimeNotify *notify) = 0; +}; + +class IOWatchFD; +class TimeWatcher; + +class ARTS_EXPORT StdIOManager : public IOManager { +protected: + std::list<IOWatchFD *> fdList; + std::list<TimeWatcher *> timeList; + std::stack<IOWatchFD *> notifyStack; + + bool terminated; + + bool fdListChanged; // causes the fd_sets to be rebuilt before using them + bool timeListChanged; + fd_set readfds, writefds, exceptfds; + fd_set reentrant_readfds, reentrant_writefds, reentrant_exceptfds; + int maxfd; + + int level; + +public: + StdIOManager(); + + void processOneEvent(bool blocking); + void run(); + void terminate(); + void watchFD(int fd, int types, IONotify *notify); + void remove(IONotify *notify, int types); + void addTimer(int milliseconds, TimeNotify *notify); + void removeTimer(TimeNotify *notify); +}; + +} + +#endif |