ObjFW  Check-in [e9b4700cb6]

Overview
Comment:Refactor OFKernelEventObserver

This moves the locked queue for actions to
OFKernelEventObserver_LockedQueue, which is now used for select and
poll, but skipped for kqueue and epoll, as they natively support changes
from another thread.

This fixes the problem that removing an object is delayed until the next
observe call - at which point it might have already been closed, meaning
the fd is no longer available. This was mainly a problem with kqueue, as
closing the fd already removed it from the kqueue, which then resulted
in an error being returned when trying to manually remove the fd from
the kqueue.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: e9b4700cb6b71e6be0c05034dcb74e755a0039b223bb0c43eecc26bef6ad3e2c
User & Date: js on 2015-12-29 21:33:07
Other Links: manifest | tags
Context
2016-01-03
00:35
Fix a regression from the previous refactorization check-in: 258b8a4944 user: js tags: trunk
2015-12-29
21:33
Refactor OFKernelEventObserver check-in: e9b4700cb6 user: js tags: trunk
2015-12-05
21:23
of{http,zip}: Better documentation of long options check-in: 227351155f user: js tags: trunk
Changes

Modified src/Makefile from [a4f5f66d7c] to [d07ba32ec9].

87
88
89
90
91
92
93
94
95
96
97

98
99
100
101
102
103
104
105
106
107
108
109
	     OFFileManager.m		\
	     OFINICategory.m		\
	     OFINIFile.m		\
	     OFSettings.m		\
	     OFZIPArchive.m		\
	     OFZIPArchiveEntry.m
SRCS_PLUGINS = OFPlugin.m
SRCS_SOCKETS = OFHTTPClient.m		\
	       OFHTTPRequest.m		\
	       OFHTTPResponse.m		\
	       OFHTTPServer.m		\

	       OFKernelEventObserver.m	\
	       OFStreamSocket.m		\
	       OFTCPSocket.m		\
	       OFUDPSocket.m		\
	       resolver.m		\
	       socket.m
SRCS_THREADS = OFCondition.m		\
	       OFMutex.m		\
	       OFRecursiveMutex.m	\
	       OFThreadPool.m		\
	       threading.m








|
|
|
|
>
|
|
|
|
|







87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
	     OFFileManager.m		\
	     OFINICategory.m		\
	     OFINIFile.m		\
	     OFSettings.m		\
	     OFZIPArchive.m		\
	     OFZIPArchiveEntry.m
SRCS_PLUGINS = OFPlugin.m
SRCS_SOCKETS = OFHTTPClient.m				\
	       OFHTTPRequest.m				\
	       OFHTTPResponse.m				\
	       OFHTTPServer.m				\
	       OFKernelEventObserver.m			\
	       OFKernelEventObserver_LockedQueue.m	\
	       OFStreamSocket.m				\
	       OFTCPSocket.m				\
	       OFUDPSocket.m				\
	       resolver.m				\
	       socket.m
SRCS_THREADS = OFCondition.m		\
	       OFMutex.m		\
	       OFRecursiveMutex.m	\
	       OFThreadPool.m		\
	       threading.m

Modified src/OFKernelEventObserver+Private.h from [2c8d4ea4a1] to [ef9792ab10].

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 */

#import "OFKernelEventObserver.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFKernelEventObserver ()
- (void)OF_addObjectForReading: (id)object;
- (void)OF_addObjectForWriting: (id)object;
- (void)OF_removeObjectForReading: (id)object;
- (void)OF_removeObjectForWriting: (id)object;
- (void)OF_processQueueAndStoreRemovedIn: (nullable OFMutableArray*)removed;
- (void)OF_processReadBuffers;
@end

OF_ASSUME_NONNULL_END







<
<
<
<
<




15
16
17
18
19
20
21





22
23
24
25
 */

#import "OFKernelEventObserver.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFKernelEventObserver ()





- (void)OF_processReadBuffers;
@end

OF_ASSUME_NONNULL_END

Modified src/OFKernelEventObserver.h from [44498ce7a3] to [4fe6de3289].

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#import "OFObject.h"

#import "socket.h"

OF_ASSUME_NONNULL_BEGIN

@class OFMutableArray OF_GENERIC(ObjectType);
@class OFMutableDictionary OF_GENERIC(KeyType, ObjectType);
@class OFDataArray;
#ifdef OF_HAVE_THREADS
@class OFMutex;
#endif
@class OFDate;

/*!
 * @protocol OFKernelEventObserverDelegate
 *	     OFKernelEventObserver.h ObjFW/OFKernelEventObserver.h
 *
 * @brief A protocol that needs to be implemented by delegates for







<
<
<
<
<







17
18
19
20
21
22
23





24
25
26
27
28
29
30
#import "OFObject.h"

#import "socket.h"

OF_ASSUME_NONNULL_BEGIN

@class OFMutableArray OF_GENERIC(ObjectType);





@class OFDate;

/*!
 * @protocol OFKernelEventObserverDelegate
 *	     OFKernelEventObserver.h ObjFW/OFKernelEventObserver.h
 *
 * @brief A protocol that needs to be implemented by delegates for
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
 */
@interface OFKernelEventObserver: OFObject
{
	OFMutableArray OF_GENERIC(id <OFReadyForReadingObserving>)
	    *_readObjects;
	OFMutableArray OF_GENERIC(id <OFReadyForWritingObserving>)
	    *_writeObjects;
	OFMutableArray *_queue;
	OFDataArray *_queueActions;
	id <OFKernelEventObserverDelegate> _delegate;
#ifdef OF_HAVE_PIPE
	int _cancelFD[2];
#else
	of_socket_t _cancelFD[2];
	struct sockaddr_in _cancelAddr;
#endif
#ifdef OF_HAVE_THREADS
	OFMutex *_mutex;
#endif
}

/*!
 * The delegate for the OFKernelEventObserver.
 */
@property OF_NULLABLE_PROPERTY (assign)
    id <OFKernelEventObserverDelegate> delegate;







<
<







<
<
<







103
104
105
106
107
108
109


110
111
112
113
114
115
116



117
118
119
120
121
122
123
 */
@interface OFKernelEventObserver: OFObject
{
	OFMutableArray OF_GENERIC(id <OFReadyForReadingObserving>)
	    *_readObjects;
	OFMutableArray OF_GENERIC(id <OFReadyForWritingObserving>)
	    *_writeObjects;


	id <OFKernelEventObserverDelegate> _delegate;
#ifdef OF_HAVE_PIPE
	int _cancelFD[2];
#else
	of_socket_t _cancelFD[2];
	struct sockaddr_in _cancelAddr;
#endif



}

/*!
 * The delegate for the OFKernelEventObserver.
 */
@property OF_NULLABLE_PROPERTY (assign)
    id <OFKernelEventObserverDelegate> delegate;

Modified src/OFKernelEventObserver.m from [d6c5a9d524] to [898e307ee4].

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

#define __NO_EXT_QNX

#include "config.h"

#include <assert.h>

#import "OFKernelEventObserver.h"
#import "OFKernelEventObserver+Private.h"
#import "OFArray.h"
#import "OFDictionary.h"
#import "OFStream.h"
#import "OFStream+Private.h"
#import "OFDataArray.h"
#ifndef OF_HAVE_PIPE
# import "OFStreamSocket.h"
#endif
#ifdef OF_HAVE_THREADS
# import "OFMutex.h"
#endif
#import "OFDate.h"

#ifdef HAVE_KQUEUE
# import "OFKernelEventObserver_kqueue.h"
#endif
#ifdef HAVE_EPOLL
# import "OFKernelEventObserver_epoll.h"







<
<



<


<



<
<
<







14
15
16
17
18
19
20


21
22
23

24
25

26
27
28



29
30
31
32
33
34
35
 * file.
 */

#define __NO_EXT_QNX

#include "config.h"



#import "OFKernelEventObserver.h"
#import "OFKernelEventObserver+Private.h"
#import "OFArray.h"

#import "OFStream.h"
#import "OFStream+Private.h"

#ifndef OF_HAVE_PIPE
# import "OFStreamSocket.h"
#endif



#import "OFDate.h"

#ifdef HAVE_KQUEUE
# import "OFKernelEventObserver_kqueue.h"
#endif
#ifdef HAVE_EPOLL
# import "OFKernelEventObserver_epoll.h"
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFOutOfRangeException.h"

#import "socket.h"
#import "socket_helpers.h"

enum {
	QUEUE_ADD = 0,
	QUEUE_REMOVE = 1,
	QUEUE_READ = 0,
	QUEUE_WRITE = 2
};
#define QUEUE_ACTION (QUEUE_ADD | QUEUE_REMOVE)

@implementation OFKernelEventObserver
@synthesize delegate = _delegate;

+ (void)initialize
{
	if (self != [OFKernelEventObserver class])
		return;







<
<
<
<
<
<
<
<







44
45
46
47
48
49
50








51
52
53
54
55
56
57
#import "OFInitializationFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFOutOfRangeException.h"

#import "socket.h"
#import "socket_helpers.h"









@implementation OFKernelEventObserver
@synthesize delegate = _delegate;

+ (void)initialize
{
	if (self != [OFKernelEventObserver class])
		return;
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
	@try {
#if !defined(OF_HAVE_PIPE) && !defined(OF_WII)
		socklen_t cancelAddrLen;
#endif

		_readObjects = [[OFMutableArray alloc] init];
		_writeObjects = [[OFMutableArray alloc] init];
		_queue = [[OFMutableArray alloc] init];
		_queueActions = [[OFDataArray alloc]
		    initWithItemSize: sizeof(int)];

#ifdef OF_HAVE_PIPE
		if (pipe(_cancelFD))
			@throw [OFInitializationFailedException
			    exceptionWithClass: [self class]];
#else
		_cancelFD[0] = _cancelFD[1] = socket(AF_INET, SOCK_DGRAM, 0);







<
<
<







91
92
93
94
95
96
97



98
99
100
101
102
103
104
	@try {
#if !defined(OF_HAVE_PIPE) && !defined(OF_WII)
		socklen_t cancelAddrLen;
#endif

		_readObjects = [[OFMutableArray alloc] init];
		_writeObjects = [[OFMutableArray alloc] init];




#ifdef OF_HAVE_PIPE
		if (pipe(_cancelFD))
			@throw [OFInitializationFailedException
			    exceptionWithClass: [self class]];
#else
		_cancelFD[0] = _cancelFD[1] = socket(AF_INET, SOCK_DGRAM, 0);
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
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
		cancelAddrLen = sizeof(_cancelAddr);
		if (of_getsockname(_cancelFD[0], (struct sockaddr*)&_cancelAddr,
		    &cancelAddrLen) != 0)
			@throw [OFInitializationFailedException
			    exceptionWithClass: [self class]];
# endif
#endif

#ifdef OF_HAVE_THREADS
		_mutex = [[OFMutex alloc] init];
#endif
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	close(_cancelFD[0]);
	if (_cancelFD[1] != _cancelFD[0])
		close(_cancelFD[1]);

#ifdef OF_WII
	of_socket_port_free(_cancelAddr.sin_port, SOCK_DGRAM);
#endif

	[_readObjects release];
	[_writeObjects release];
	[_queue release];
	[_queueActions release];
#ifdef OF_HAVE_THREADS
	[_mutex release];
#endif

	[super dealloc];
}

- (void)addObjectForReading: (id <OFReadyForReadingObserving>)object
{
#ifdef OF_HAVE_THREADS
	[_mutex lock];
#endif
	@try {
		int qi = QUEUE_ADD | QUEUE_READ;

		[_queue addObject: object];
		[_queueActions addItem: &qi];
	} @finally {
#ifdef OF_HAVE_THREADS
		[_mutex unlock];
#endif
	}

	[self cancel];
}

- (void)addObjectForWriting: (id <OFReadyForWritingObserving>)object
{
#ifdef OF_HAVE_THREADS
	[_mutex lock];
#endif
	@try {
		int qi = QUEUE_ADD | QUEUE_WRITE;

		[_queue addObject: object];
		[_queueActions addItem: &qi];
	} @finally {
#ifdef OF_HAVE_THREADS
		[_mutex unlock];
#endif
	}

	[self cancel];
}

- (void)removeObjectForReading: (id <OFReadyForReadingObserving>)object
{
#ifdef OF_HAVE_THREADS
	[_mutex lock];
#endif
	@try {
		int qi = QUEUE_REMOVE | QUEUE_READ;

		[_queue addObject: object];
		[_queueActions addItem: &qi];
	} @finally {
#ifdef OF_HAVE_THREADS
		[_mutex unlock];
#endif
	}

	[self cancel];
}

- (void)removeObjectForWriting: (id <OFReadyForWritingObserving>)object
{
#ifdef OF_HAVE_THREADS
	[_mutex lock];
#endif
	@try {
		int qi = QUEUE_REMOVE | QUEUE_WRITE;

		[_queue addObject: object];
		[_queueActions addItem: &qi];
	} @finally {
#ifdef OF_HAVE_THREADS
		[_mutex unlock];
#endif
	}

	[self cancel];
}

- (void)OF_addObjectForReading: (id)object
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)OF_addObjectForWriting: (id)object
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)OF_removeObjectForReading: (id)object
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)OF_removeObjectForWriting: (id)object
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)OF_processQueueAndStoreRemovedIn: (OFMutableArray*)removed
{
#ifdef OF_HAVE_THREADS
	[_mutex lock];
#endif
	@try {
		id const *queueObjects = [_queue objects];
		int *queueActionItems = [_queueActions items];
		size_t i, count = [_queue count];

		for (i = 0; i < count; i++) {
			id object = queueObjects[i];
			int action = queueActionItems[i];

			switch (action) {
			case QUEUE_ADD | QUEUE_READ:
				[_readObjects addObject: object];

				[self OF_addObjectForReading: object];

				break;
			case QUEUE_ADD | QUEUE_WRITE:
				[_writeObjects addObject: object];

				[self OF_addObjectForWriting: object];

				break;
			case QUEUE_REMOVE | QUEUE_READ:
				[self OF_removeObjectForReading: object];

				[removed addObject: object];
				[_readObjects removeObjectIdenticalTo: object];

				break;
			case QUEUE_REMOVE | QUEUE_WRITE:
				[self OF_removeObjectForWriting: object];

				[removed addObject: object];
				[_writeObjects removeObjectIdenticalTo: object];

				break;
			default:
				assert(0);
			}
		}

		[_queue removeAllObjects];
		[_queueActions removeAllItems];
	} @finally {
#ifdef OF_HAVE_THREADS
		[_mutex unlock];
#endif
	}
}

- (void)observe
{
	[self observeForTimeInterval: -1];
}








<
<
<
<




















<
<
<
<
<






<
<
<
<
<
|
<
<
<
<
<
<
|

<
<
<


<
<
<
<
<
|
<
<
<
<
<
<
|

<
<
<


<
<
<
<
<
|
<
<
<
<
<
<
<
<
<




<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







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
		cancelAddrLen = sizeof(_cancelAddr);
		if (of_getsockname(_cancelFD[0], (struct sockaddr*)&_cancelAddr,
		    &cancelAddrLen) != 0)
			@throw [OFInitializationFailedException
			    exceptionWithClass: [self class]];
# endif
#endif




	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	close(_cancelFD[0]);
	if (_cancelFD[1] != _cancelFD[0])
		close(_cancelFD[1]);

#ifdef OF_WII
	of_socket_port_free(_cancelAddr.sin_port, SOCK_DGRAM);
#endif

	[_readObjects release];
	[_writeObjects release];






	[super dealloc];
}

- (void)addObjectForReading: (id <OFReadyForReadingObserving>)object
{





	OF_UNRECOGNIZED_SELECTOR






}




- (void)addObjectForWriting: (id <OFReadyForWritingObserving>)object
{





	OF_UNRECOGNIZED_SELECTOR






}




- (void)removeObjectForReading: (id <OFReadyForReadingObserving>)object
{





	OF_UNRECOGNIZED_SELECTOR









}

- (void)removeObjectForWriting: (id <OFReadyForWritingObserving>)object
{



















	OF_UNRECOGNIZED_SELECTOR






































































}

- (void)observe
{
	[self observeForTimeInterval: -1];
}

Added src/OFKernelEventObserver_LockedQueue.h version [e60316af1b].































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*
 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFKernelEventObserver.h"

OF_ASSUME_NONNULL_BEGIN

@class OFMutableArray OF_GENERIC(ObjectType);
@class OFDataArray;
#ifdef OF_HAVE_THREADS
@class OFMutex;
#endif

@interface OFKernelEventObserver_LockedQueue: OFKernelEventObserver
{
	OFDataArray *_queueActions, *_queueFDs;
	OFMutableArray *_queueObjects;
#ifdef OF_HAVE_THREADS
	OFMutex *_mutex;
#endif
}

- (void)OF_addObjectForReading: (id)object
		fileDescriptor: (int)fd;
- (void)OF_addObjectForWriting: (id)object
		fileDescriptor: (int)fd;
- (void)OF_removeObjectForReading: (id)object
		   fileDescriptor: (int)fd;
- (void)OF_removeObjectForWriting: (id)object
		   fileDescriptor: (int)fd;
- (void)OF_processQueue;
@end

OF_ASSUME_NONNULL_END

Added src/OFKernelEventObserver_LockedQueue.m version [dc0778aa90].

































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
/*
 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015
 *   Jonathan Schleifer <js@webkeks.org>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#import "OFKernelEventObserver_LockedQueue.h"
#import "OFArray.h"
#import "OFDataArray.h"
#ifdef OF_HAVE_THREADS
# import "OFMutex.h"
#endif

#import "OFInitializationFailedException.h"

enum {
	QUEUE_ADD = 0,
	QUEUE_REMOVE = 1,
	QUEUE_READ = 0,
	QUEUE_WRITE = 2
};
#define QUEUE_ACTION (QUEUE_ADD | QUEUE_REMOVE)

@implementation OFKernelEventObserver_LockedQueue
- init
{
	self = [super init];

	@try {
		_queueActions = [[OFDataArray alloc]
		    initWithItemSize: sizeof(int)];
		_queueFDs = [[OFDataArray alloc] initWithItemSize: sizeof(int)];
		_queueObjects = [[OFMutableArray alloc] init];

#ifdef OF_HAVE_THREADS
		_mutex = [[OFMutex alloc] init];
#endif
	} @catch (id e) {
		@throw [OFInitializationFailedException
		    exceptionWithClass: [self class]];
	}

	return self;
}

- (void)dealloc
{
	[_queueActions release];
	[_queueFDs release];
	[_queueObjects release];
#ifdef OF_HAVE_THREADS
	[_mutex release];
#endif

	[super dealloc];
}

- (void)addObjectForReading: (id <OFReadyForReadingObserving>)object
{
#ifdef OF_HAVE_THREADS
	[_mutex lock];
	@try {
#endif
		int qi = QUEUE_ADD | QUEUE_READ;
		int fd = [object fileDescriptorForReading];

		[_queueActions addItem: &qi];
		[_queueFDs addItem: &fd];
		[_queueObjects addObject: object];
#ifdef OF_HAVE_THREADS
	} @finally {
		[_mutex unlock];
	}
#endif

	[self cancel];
}

- (void)addObjectForWriting: (id <OFReadyForWritingObserving>)object
{
#ifdef OF_HAVE_THREADS
	[_mutex lock];
	@try {
#endif
		int qi = QUEUE_ADD | QUEUE_WRITE;
		int fd = [object fileDescriptorForWriting];

		[_queueActions addItem: &qi];
		[_queueFDs addItem: &fd];
		[_queueObjects addObject: object];
#ifdef OF_HAVE_THREADS
	} @finally {
		[_mutex unlock];
	}
#endif

	[self cancel];
}

- (void)removeObjectForReading: (id <OFReadyForReadingObserving>)object
{
#ifdef OF_HAVE_THREADS
	[_mutex lock];
	@try {
#endif
		int qi = QUEUE_REMOVE | QUEUE_READ;
		int fd = [object fileDescriptorForReading];

		[_queueActions addItem: &qi];
		[_queueFDs addItem: &fd];
		[_queueObjects addObject: object];
#ifdef OF_HAVE_THREADS
	} @finally {
		[_mutex unlock];
	}
#endif

	[self cancel];
}

- (void)removeObjectForWriting: (id <OFReadyForWritingObserving>)object
{
#ifdef OF_HAVE_THREADS
	[_mutex lock];
	@try {
#endif
		int qi = QUEUE_REMOVE | QUEUE_WRITE;
		int fd = [object fileDescriptorForWriting];

		[_queueActions addItem: &qi];
		[_queueFDs addItem: &fd];
		[_queueObjects addObject: object];
#ifdef OF_HAVE_THREADS
	} @finally {
		[_mutex unlock];
	}
#endif

	[self cancel];
}

- (void)OF_addObjectForReading: (id)object
		fileDescriptor: (int)fd
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)OF_addObjectForWriting: (id)object
		fileDescriptor: (int)fd
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)OF_removeObjectForReading: (id)object
		   fileDescriptor: (int)fd
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)OF_removeObjectForWriting: (id)object
		   fileDescriptor: (int)fd
{
	OF_UNRECOGNIZED_SELECTOR
}

- (void)OF_processQueue
{
#ifdef OF_HAVE_THREADS
	[_mutex lock];
	@try {
#endif
		int *queueActions = [_queueActions items];
		int *queueFDs = [_queueFDs items];
		id const *queueObjects = [_queueObjects objects];
		size_t i, count = [_queueActions count];

		OF_ENSURE([_queueFDs count] == count);
		OF_ENSURE([_queueObjects count] == count);

		for (i = 0; i < count; i++) {
			int action = queueActions[i];
			int fd = queueFDs[i];
			id object = queueObjects[i];

			switch (action) {
			case QUEUE_ADD | QUEUE_READ:
				[_readObjects addObject: object];

				[self OF_addObjectForReading: object
					      fileDescriptor: fd];

				break;
			case QUEUE_ADD | QUEUE_WRITE:
				[_writeObjects addObject: object];

				[self OF_addObjectForWriting: object
					      fileDescriptor: fd];

				break;
			case QUEUE_REMOVE | QUEUE_READ:
				[self OF_removeObjectForReading: object
						 fileDescriptor: fd];

				[_readObjects removeObjectIdenticalTo: object];

				break;
			case QUEUE_REMOVE | QUEUE_WRITE:
				[self OF_removeObjectForWriting: object
						 fileDescriptor: fd];

				[_writeObjects removeObjectIdenticalTo: object];

				break;
			default:
				OF_ENSURE(0);
			}
		}

		[_queueActions removeAllItems];
		[_queueFDs removeAllItems];
		[_queueObjects removeAllObjects];
#ifdef OF_HAVE_THREADS
	} @finally {
		[_mutex unlock];
	}
#endif
}
@end

Modified src/OFKernelEventObserver_epoll.m from [48f0674f49] to [02fb70080b].

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
					    errNo: errno];

		[_FDToEvents setValue: (void*)events
			       forKey: (void*)(intptr_t)fd];
	}
}

- (void)OF_addObjectForReading: (id)object
{
	[self OF_addObject: object
	    fileDescriptor: [object fileDescriptorForReading]
		    events: EPOLLIN];
}

- (void)OF_addObjectForWriting: (id)object
{
	[self OF_addObject: object
	    fileDescriptor: [object fileDescriptorForWriting]
		    events: EPOLLOUT];
}

- (void)OF_removeObjectForReading: (id)object
{
	[self OF_removeObject: object
	       fileDescriptor: [object fileDescriptorForReading]
		       events: EPOLLIN];
}

- (void)OF_removeObjectForWriting: (id)object
{
	[self OF_removeObject: object
	       fileDescriptor: [object fileDescriptorForWriting]
		       events: EPOLLOUT];
}

- (void)observeForTimeInterval: (of_time_interval_t)timeInterval
{
	OFNull *nullObject = [OFNull null];
	void *pool = objc_autoreleasePoolPush();
	struct epoll_event eventList[EVENTLIST_SIZE];
	int i, events;

	[self OF_processQueueAndStoreRemovedIn: nil];
	[self OF_processReadBuffers];

	objc_autoreleasePoolPop(pool);

	events = epoll_wait(_epfd, eventList, EVENTLIST_SIZE,
	    (timeInterval != -1 ? timeInterval * 1000 : -1));








|






|






|






|













<







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
					    errNo: errno];

		[_FDToEvents setValue: (void*)events
			       forKey: (void*)(intptr_t)fd];
	}
}

- (void)addObjectForReading: (id <OFReadyForReadingObserving>)object
{
	[self OF_addObject: object
	    fileDescriptor: [object fileDescriptorForReading]
		    events: EPOLLIN];
}

- (void)addObjectForWriting: (id <OFReadyForWritingObserving>)object
{
	[self OF_addObject: object
	    fileDescriptor: [object fileDescriptorForWriting]
		    events: EPOLLOUT];
}

- (void)removeObjectForReading: (id <OFReadyForReadingObserving>)object
{
	[self OF_removeObject: object
	       fileDescriptor: [object fileDescriptorForReading]
		       events: EPOLLIN];
}

- (void)removeObjectForWriting: (id <OFReadyForWritingObserving>)object
{
	[self OF_removeObject: object
	       fileDescriptor: [object fileDescriptorForWriting]
		       events: EPOLLOUT];
}

- (void)observeForTimeInterval: (of_time_interval_t)timeInterval
{
	OFNull *nullObject = [OFNull null];
	void *pool = objc_autoreleasePoolPush();
	struct epoll_event eventList[EVENTLIST_SIZE];
	int i, events;


	[self OF_processReadBuffers];

	objc_autoreleasePoolPop(pool);

	events = epoll_wait(_epfd, eventList, EVENTLIST_SIZE,
	    (timeInterval != -1 ? timeInterval * 1000 : -1));

Modified src/OFKernelEventObserver_kqueue.h from [59a7d7f5c7] to [e4af935bfd].

20
21
22
23
24
25
26
27
28
29
30
31
32

@class OFDataArray;
@class OFMutableArray OF_GENERIC(ObjectType);

@interface OFKernelEventObserver_kqueue: OFKernelEventObserver
{
	int _kernelQueue;
	OFDataArray *_changeList;
	OFMutableArray *_removedArray;
}
@end

OF_ASSUME_NONNULL_END







<
<




20
21
22
23
24
25
26


27
28
29
30

@class OFDataArray;
@class OFMutableArray OF_GENERIC(ObjectType);

@interface OFKernelEventObserver_kqueue: OFKernelEventObserver
{
	int _kernelQueue;


}
@end

OF_ASSUME_NONNULL_END

Modified src/OFKernelEventObserver_kqueue.m from [80111af3e0] to [3ad5dffb1b].

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
			@throw [OFInitializationFailedException
			    exceptionWithClass: [self class]];

		if ((flags = fcntl(_kernelQueue, F_GETFD, 0)) != -1)
			fcntl(_kernelQueue, F_SETFD, flags | FD_CLOEXEC);
#endif

		_changeList = [[OFDataArray alloc] initWithItemSize:
		    sizeof(struct kevent)];
		EV_SET(&event, _cancelFD[0], EVFILT_READ, EV_ADD, 0, 0, 0);
		[_changeList addItem: &event];

		_removedArray = [[OFMutableArray alloc] init];



	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	close(_kernelQueue);

	[_changeList release];
	[_removedArray release];

	[super dealloc];
}

- (void)OF_addObjectForReading: (id)object
{
	struct kevent event;

	if ([_changeList count] >= INT_MAX)
		@throw [OFOutOfRangeException exception];

	memset(&event, 0, sizeof(event));
	event.ident = [object fileDescriptorForReading];
	event.filter = EVFILT_READ;
	event.flags = EV_ADD;
#ifndef OF_NETBSD
	event.udata = object;
#else
	event.udata = (intptr_t)object;
#endif

	[_changeList addItem: &event];



}

- (void)OF_addObjectForWriting: (id)object
{
	struct kevent event;

	if ([_changeList count] >= INT_MAX)
		@throw [OFOutOfRangeException exception];

	memset(&event, 0, sizeof(event));
	event.ident = [object fileDescriptorForWriting];
	event.filter = EVFILT_WRITE;
	event.flags = EV_ADD;
#ifndef OF_NETBSD
	event.udata = object;
#else
	event.udata = (intptr_t)object;
#endif

	[_changeList addItem: &event];



}

- (void)OF_removeObjectForReading: (id)object
{
	struct kevent event;

	memset(&event, 0, sizeof(event));
	event.ident = [object fileDescriptorForReading];
	event.filter = EVFILT_READ;
	event.flags = EV_DELETE;
	[_changeList addItem: &event];




}

- (void)OF_removeObjectForWriting: (id)object
{
	struct kevent event;

	memset(&event, 0, sizeof(event));
	event.ident = [object fileDescriptorForWriting];
	event.filter = EVFILT_WRITE;
	event.flags = EV_DELETE;
	[_changeList addItem: &event];




}

- (void)observeForTimeInterval: (of_time_interval_t)timeInterval
{
	void *pool = objc_autoreleasePoolPush();
	struct timespec timeout;
	struct kevent eventList[EVENTLIST_SIZE];
	int i, events;

	timeout.tv_sec = (time_t)timeInterval;
	timeout.tv_nsec = lrint((timeInterval - timeout.tv_sec) * 1000000000);

	/*
	 * Make sure to keep the streams retained and thus the file descriptors
	 * valid until the actual change has been performed.
	 */
	[self OF_processQueueAndStoreRemovedIn: _removedArray];

	[self OF_processReadBuffers];

	objc_autoreleasePoolPop(pool);

	events = kevent(_kernelQueue, [_changeList items],
	    (int)[_changeList count], eventList, EVENTLIST_SIZE,
	    (timeInterval != -1 ? &timeout : NULL));

	if (events < 0)
		@throw [OFObserveFailedException exceptionWithObserver: self
								 errNo: errno];

	[_changeList removeAllItems];
	[_removedArray removeAllObjects];

	for (i = 0; i < events; i++) {
		if (eventList[i].flags & EV_ERROR)
			@throw [OFObserveFailedException
			    exceptionWithObserver: self
					    errNo: (int)eventList[i].data];

		if (eventList[i].ident == _cancelFD[0]) {







<
<

<

<
>
>
>












<
<
<



|



<
<
<










|
>
>
>


|



<
<
<










|
>
>
>


|







|
>
>
>
>


|







|
>
>
>
>












<
<
<
<
<
<




|
<






<
<
<







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
			@throw [OFInitializationFailedException
			    exceptionWithClass: [self class]];

		if ((flags = fcntl(_kernelQueue, F_GETFD, 0)) != -1)
			fcntl(_kernelQueue, F_SETFD, flags | FD_CLOEXEC);
#endif



		EV_SET(&event, _cancelFD[0], EVFILT_READ, EV_ADD, 0, 0, 0);



		if (kevent(_kernelQueue, &event, 1, NULL, 0, NULL) != 0)
			@throw [OFInitializationFailedException
			    exceptionWithClass: [self class]];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	close(_kernelQueue);




	[super dealloc];
}

- (void)addObjectForReading: (id <OFReadyForReadingObserving>)object
{
	struct kevent event;




	memset(&event, 0, sizeof(event));
	event.ident = [object fileDescriptorForReading];
	event.filter = EVFILT_READ;
	event.flags = EV_ADD;
#ifndef OF_NETBSD
	event.udata = object;
#else
	event.udata = (intptr_t)object;
#endif

	if (kevent(_kernelQueue, &event, 1, NULL, 0, NULL) != 0)
		@throw [OFObserveFailedException
		    exceptionWithObserver: self
				    errNo: errno];
}

- (void)addObjectForWriting: (id <OFReadyForWritingObserving>)object
{
	struct kevent event;




	memset(&event, 0, sizeof(event));
	event.ident = [object fileDescriptorForWriting];
	event.filter = EVFILT_WRITE;
	event.flags = EV_ADD;
#ifndef OF_NETBSD
	event.udata = object;
#else
	event.udata = (intptr_t)object;
#endif

	if (kevent(_kernelQueue, &event, 1, NULL, 0, NULL) != 0)
		@throw [OFObserveFailedException
		    exceptionWithObserver: self
				    errNo: errno];
}

- (void)removeObjectForReading: (id <OFReadyForReadingObserving>)object
{
	struct kevent event;

	memset(&event, 0, sizeof(event));
	event.ident = [object fileDescriptorForReading];
	event.filter = EVFILT_READ;
	event.flags = EV_DELETE;

	if (kevent(_kernelQueue, &event, 1, NULL, 0, NULL) != 0)
		@throw [OFObserveFailedException
		    exceptionWithObserver: self
				    errNo: errno];
}

- (void)removeObjectForWriting: (id <OFReadyForWritingObserving>)object
{
	struct kevent event;

	memset(&event, 0, sizeof(event));
	event.ident = [object fileDescriptorForWriting];
	event.filter = EVFILT_WRITE;
	event.flags = EV_DELETE;

	if (kevent(_kernelQueue, &event, 1, NULL, 0, NULL) != 0)
		@throw [OFObserveFailedException
		    exceptionWithObserver: self
				    errNo: errno];
}

- (void)observeForTimeInterval: (of_time_interval_t)timeInterval
{
	void *pool = objc_autoreleasePoolPush();
	struct timespec timeout;
	struct kevent eventList[EVENTLIST_SIZE];
	int i, events;

	timeout.tv_sec = (time_t)timeInterval;
	timeout.tv_nsec = lrint((timeInterval - timeout.tv_sec) * 1000000000);







	[self OF_processReadBuffers];

	objc_autoreleasePoolPop(pool);

	events = kevent(_kernelQueue, NULL, 0, eventList, EVENTLIST_SIZE,

	    (timeInterval != -1 ? &timeout : NULL));

	if (events < 0)
		@throw [OFObserveFailedException exceptionWithObserver: self
								 errNo: errno];




	for (i = 0; i < events; i++) {
		if (eventList[i].flags & EV_ERROR)
			@throw [OFObserveFailedException
			    exceptionWithObserver: self
					    errNo: (int)eventList[i].data];

		if (eventList[i].ident == _cancelFD[0]) {

Modified src/OFKernelEventObserver_poll.h from [2642239f58] to [c6cbfa2ee8].

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFKernelEventObserver.h"

OF_ASSUME_NONNULL_BEGIN

@class OFDataArray;

@interface OFKernelEventObserver_poll: OFKernelEventObserver
{
	OFDataArray *_FDs;
	size_t _maxFD;
	id __unsafe_unretained *_FDToObject;
}
@end

OF_ASSUME_NONNULL_END







|





|








10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#import "OFKernelEventObserver_LockedQueue.h"

OF_ASSUME_NONNULL_BEGIN

@class OFDataArray;

@interface OFKernelEventObserver_poll: OFKernelEventObserver_LockedQueue
{
	OFDataArray *_FDs;
	size_t _maxFD;
	id __unsafe_unretained *_FDToObject;
}
@end

OF_ASSUME_NONNULL_END

Modified src/OFKernelEventObserver_poll.m from [14102c57fc] to [66c27474d9].

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

			break;
		}
	}
}

- (void)OF_addObjectForReading: (id)object

{
	[self OF_addObject: object
	    fileDescriptor: [object fileDescriptorForReading]
		    events: POLLIN];
}

- (void)OF_addObjectForWriting: (id)object

{
	[self OF_addObject: object
	    fileDescriptor: [object fileDescriptorForWriting]
		    events: POLLOUT];
}

- (void)OF_removeObjectForReading: (id)object

{
	[self OF_removeObject: object
	       fileDescriptor: [object fileDescriptorForReading]
		       events: POLLIN];
}

- (void)OF_removeObjectForWriting: (id)object

{
	[self OF_removeObject: object
	       fileDescriptor: [object fileDescriptorForWriting]
		       events: POLLOUT];
}

- (void)observeForTimeInterval: (of_time_interval_t)timeInterval
{
	void *pool = objc_autoreleasePoolPush();
	struct pollfd *FDs;
	int events;
	size_t i, nFDs;

	[self OF_processQueueAndStoreRemovedIn: nil];
	[self OF_processReadBuffers];

	objc_autoreleasePoolPop(pool);

	FDs = [_FDs items];
	nFDs = [_FDs count];








>


|




>


|




>


|




>


|










|







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

			break;
		}
	}
}

- (void)OF_addObjectForReading: (id)object
		fileDescriptor: (int)fd
{
	[self OF_addObject: object
	    fileDescriptor: fd
		    events: POLLIN];
}

- (void)OF_addObjectForWriting: (id)object
		fileDescriptor: (int)fd
{
	[self OF_addObject: object
	    fileDescriptor: fd
		    events: POLLOUT];
}

- (void)OF_removeObjectForReading: (id)object
		   fileDescriptor: (int)fd
{
	[self OF_removeObject: object
	       fileDescriptor: fd
		       events: POLLIN];
}

- (void)OF_removeObjectForWriting: (id)object
		   fileDescriptor: (int)fd
{
	[self OF_removeObject: object
	       fileDescriptor: fd
		       events: POLLOUT];
}

- (void)observeForTimeInterval: (of_time_interval_t)timeInterval
{
	void *pool = objc_autoreleasePoolPush();
	struct pollfd *FDs;
	int events;
	size_t i, nFDs;

	[self OF_processQueue];
	[self OF_processReadBuffers];

	objc_autoreleasePoolPop(pool);

	FDs = [_FDs items];
	nFDs = [_FDs count];

Modified src/OFKernelEventObserver_select.h from [9b429b52d8] to [8eed9130ce].

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# define __STDC_CONSTANT_MACROS
#endif

#ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
#endif

#import "OFKernelEventObserver.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFKernelEventObserver_select: OFKernelEventObserver
{
	fd_set _readFDs, _writeFDs;
	int _maxFD;
}
@end

OF_ASSUME_NONNULL_END







|



|







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# define __STDC_CONSTANT_MACROS
#endif

#ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
#endif

#import "OFKernelEventObserver_LockedQueue.h"

OF_ASSUME_NONNULL_BEGIN

@interface OFKernelEventObserver_select: OFKernelEventObserver_LockedQueue
{
	fd_set _readFDs, _writeFDs;
	int _maxFD;
}
@end

OF_ASSUME_NONNULL_END

Modified src/OFKernelEventObserver_select.m from [46057c9c67] to [8f0b3058db].

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

	_maxFD = (int)_cancelFD[0];

	return self;
}

- (void)OF_addObjectForReading: (id)object
{
	int fd = [object fileDescriptorForReading];

	if (fd < 0 || fd > INT_MAX - 1)
		@throw [OFOutOfRangeException exception];

#ifndef OF_WINDOWS
	if (fd >= FD_SETSIZE)
		@throw [OFOutOfRangeException exception];
#endif

	if (fd > _maxFD)
		_maxFD = fd;

	FD_SET(fd, &_readFDs);
}

- (void)OF_addObjectForWriting: (id)object
{
	int fd = [object fileDescriptorForWriting];

	if (fd < 0 || fd > INT_MAX - 1)
		@throw [OFOutOfRangeException exception];

#ifndef OF_WINDOWS
	if (fd >= FD_SETSIZE)
		@throw [OFOutOfRangeException exception];
#endif

	if (fd > _maxFD)
		_maxFD = fd;

	FD_SET(fd, &_writeFDs);
}

- (void)OF_removeObjectForReading: (id)object

{
	/* TODO: Adjust _maxFD */

	int fd = [object fileDescriptorForReading];

	if (fd < 0)
		@throw [OFOutOfRangeException exception];

#ifndef OF_WINDOWS
	if (fd >= FD_SETSIZE)
		@throw [OFOutOfRangeException exception];
#endif

	FD_CLR(fd, &_readFDs);
}

- (void)OF_removeObjectForWriting: (id)object

{
	/* TODO: Adjust _maxFD */

	int fd = [object fileDescriptorForWriting];

	if (fd < 0)
		@throw [OFOutOfRangeException exception];

#ifndef OF_WINDOWS
	if (fd >= FD_SETSIZE)
		@throw [OFOutOfRangeException exception];
#endif







<
|
|















<
|
|















>



<
<












>



<
<







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

	_maxFD = (int)_cancelFD[0];

	return self;
}

- (void)OF_addObjectForReading: (id)object

		fileDescriptor: (int)fd
{
	if (fd < 0 || fd > INT_MAX - 1)
		@throw [OFOutOfRangeException exception];

#ifndef OF_WINDOWS
	if (fd >= FD_SETSIZE)
		@throw [OFOutOfRangeException exception];
#endif

	if (fd > _maxFD)
		_maxFD = fd;

	FD_SET(fd, &_readFDs);
}

- (void)OF_addObjectForWriting: (id)object

		fileDescriptor: (int)fd
{
	if (fd < 0 || fd > INT_MAX - 1)
		@throw [OFOutOfRangeException exception];

#ifndef OF_WINDOWS
	if (fd >= FD_SETSIZE)
		@throw [OFOutOfRangeException exception];
#endif

	if (fd > _maxFD)
		_maxFD = fd;

	FD_SET(fd, &_writeFDs);
}

- (void)OF_removeObjectForReading: (id)object
		   fileDescriptor: (int)fd
{
	/* TODO: Adjust _maxFD */



	if (fd < 0)
		@throw [OFOutOfRangeException exception];

#ifndef OF_WINDOWS
	if (fd >= FD_SETSIZE)
		@throw [OFOutOfRangeException exception];
#endif

	FD_CLR(fd, &_readFDs);
}

- (void)OF_removeObjectForWriting: (id)object
		   fileDescriptor: (int)fd
{
	/* TODO: Adjust _maxFD */



	if (fd < 0)
		@throw [OFOutOfRangeException exception];

#ifndef OF_WINDOWS
	if (fd >= FD_SETSIZE)
		@throw [OFOutOfRangeException exception];
#endif
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
	id const *objects;
	fd_set readFDs;
	fd_set writeFDs;
	struct timeval timeout;
	int events;
	size_t i, count;

	[self OF_processQueueAndStoreRemovedIn: nil];
	[self OF_processReadBuffers];

	objc_autoreleasePoolPop(pool);

#ifdef FD_COPY
	FD_COPY(&_readFDs, &readFDs);
	FD_COPY(&_writeFDs, &writeFDs);







|







136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
	id const *objects;
	fd_set readFDs;
	fd_set writeFDs;
	struct timeval timeout;
	int events;
	size_t i, count;

	[self OF_processQueue];
	[self OF_processReadBuffers];

	objc_autoreleasePoolPop(pool);

#ifdef FD_COPY
	FD_COPY(&_readFDs, &readFDs);
	FD_COPY(&_writeFDs, &writeFDs);