summaryrefslogtreecommitdiffstats
path: root/mcop/iomanager.h
blob: a226e0cd634709ca4660b89651e453d613da427e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
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