You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
arts/mcop/iomanager.h

215 lines
5.6 KiB

/*
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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, 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