|
|
|
/*
|
|
|
|
|
|
|
|
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
|