Index: src/OFKernelEventObserver+Private.h ================================================================== --- src/OFKernelEventObserver+Private.h +++ src/OFKernelEventObserver+Private.h @@ -15,12 +15,12 @@ */ #import "OFKernelEventObserver.h" @interface OFKernelEventObserver (OF_PRIVATE_CATEGORY) -- (void)OF_addFileDescriptorForReading: (int)fd; -- (void)OF_addFileDescriptorForWriting: (int)fd; -- (void)OF_removeFileDescriptorForReading: (int)fd; -- (void)OF_removeFileDescriptorForWriting: (int)fd; +- (void)OF_addObjectForReading: (id)object; +- (void)OF_addObjectForWriting: (id)object; +- (void)OF_removeObjectForReading: (id)object; +- (void)OF_removeObjectForWriting: (id)object; - (void)OF_processQueueAndStoreRemovedIn: (OFMutableArray*)removed; - (bool)OF_processReadBuffers; @end Index: src/OFKernelEventObserver.h ================================================================== --- src/OFKernelEventObserver.h +++ src/OFKernelEventObserver.h @@ -108,14 +108,12 @@ */ @interface OFKernelEventObserver: OFObject { OFMutableArray *_readObjects; OFMutableArray *_writeObjects; - __unsafe_unretained id *_FDToObject; - size_t _maxFD; OFMutableArray *_queue; - OFDataArray *_queueInfo, *_queueFDs; + OFDataArray *_queueActions; id _delegate; #ifdef OF_HAVE_PIPE int _cancelFD[2]; #else of_socket_t _cancelFD[2]; Index: src/OFKernelEventObserver.m ================================================================== --- src/OFKernelEventObserver.m +++ src/OFKernelEventObserver.m @@ -107,13 +107,12 @@ #endif _readObjects = [[OFMutableArray alloc] init]; _writeObjects = [[OFMutableArray alloc] init]; _queue = [[OFMutableArray alloc] init]; - _queueInfo = [[OFDataArray alloc] + _queueActions = [[OFDataArray alloc] initWithItemSize: sizeof(int)]; - _queueFDs = [[OFDataArray alloc] initWithItemSize: sizeof(int)]; #ifdef OF_HAVE_PIPE if (pipe(_cancelFD)) @throw [OFInitializationFailedException exceptionWithClass: [self class]]; @@ -145,15 +144,10 @@ @throw [OFInitializationFailedException exceptionWithClass: [self class]]; # endif #endif - _maxFD = _cancelFD[0]; - _FDToObject = [self allocMemoryWithSize: sizeof(id) - count: _maxFD + 1]; - _FDToObject[_cancelFD[0]] = nil; - #ifdef OF_HAVE_THREADS _mutex = [[OFMutex alloc] init]; #endif } @catch (id e) { [self release]; @@ -170,12 +164,11 @@ close(_cancelFD[1]); [_readObjects release]; [_writeObjects release]; [_queue release]; - [_queueInfo release]; - [_queueFDs release]; + [_queueActions release]; #ifdef OF_HAVE_THREADS [_mutex release]; #endif [super dealloc]; @@ -196,15 +189,13 @@ #ifdef OF_HAVE_THREADS [_mutex lock]; #endif @try { int qi = QUEUE_ADD | QUEUE_READ; - int fd = [object fileDescriptorForReading]; [_queue addObject: object]; - [_queueInfo addItem: &qi]; - [_queueFDs addItem: &fd]; + [_queueActions addItem: &qi]; } @finally { #ifdef OF_HAVE_THREADS [_mutex unlock]; #endif } @@ -217,15 +208,13 @@ #ifdef OF_HAVE_THREADS [_mutex lock]; #endif @try { int qi = QUEUE_ADD | QUEUE_WRITE; - int fd = [object fileDescriptorForWriting]; [_queue addObject: object]; - [_queueInfo addItem: &qi]; - [_queueFDs addItem: &fd]; + [_queueActions addItem: &qi]; } @finally { #ifdef OF_HAVE_THREADS [_mutex unlock]; #endif } @@ -238,15 +227,13 @@ #ifdef OF_HAVE_THREADS [_mutex lock]; #endif @try { int qi = QUEUE_REMOVE | QUEUE_READ; - int fd = [object fileDescriptorForReading]; [_queue addObject: object]; - [_queueInfo addItem: &qi]; - [_queueFDs addItem: &fd]; + [_queueActions addItem: &qi]; } @finally { #ifdef OF_HAVE_THREADS [_mutex unlock]; #endif } @@ -259,40 +246,38 @@ #ifdef OF_HAVE_THREADS [_mutex lock]; #endif @try { int qi = QUEUE_REMOVE | QUEUE_WRITE; - int fd = [object fileDescriptorForWriting]; [_queue addObject: object]; - [_queueInfo addItem: &qi]; - [_queueFDs addItem: &fd]; + [_queueActions addItem: &qi]; } @finally { #ifdef OF_HAVE_THREADS [_mutex unlock]; #endif } [self cancel]; } -- (void)OF_addFileDescriptorForReading: (int)fd +- (void)OF_addObjectForReading: (id)object +{ + OF_UNRECOGNIZED_SELECTOR +} + +- (void)OF_addObjectForWriting: (id)object { OF_UNRECOGNIZED_SELECTOR } -- (void)OF_addFileDescriptorForWriting: (int)fd +- (void)OF_removeObjectForReading: (id)object { OF_UNRECOGNIZED_SELECTOR } -- (void)OF_removeFileDescriptorForReading: (int)fd -{ - OF_UNRECOGNIZED_SELECTOR -} - -- (void)OF_removeFileDescriptorForWriting: (int)fd +- (void)OF_removeObjectForWriting: (id)object { OF_UNRECOGNIZED_SELECTOR } - (void)OF_processQueueAndStoreRemovedIn: (OFMutableArray*)removed @@ -300,61 +285,39 @@ #ifdef OF_HAVE_THREADS [_mutex lock]; #endif @try { id const *queueObjects = [_queue objects]; - int *queueInfoItems = [_queueInfo items]; - int *queueFDsItems = [_queueFDs items]; + int *queueActionItems = [_queueActions items]; size_t i, count = [_queue count]; for (i = 0; i < count; i++) { id object = queueObjects[i]; - int action = queueInfoItems[i]; - int fd = queueFDsItems[i]; - - if ((action & QUEUE_ACTION) == QUEUE_ADD) { - if (fd > _maxFD) { - _maxFD = fd; - _FDToObject = [self - resizeMemory: _FDToObject - size: sizeof(id) - count: _maxFD + 1]; - } - - _FDToObject[fd] = object; - } - - if ((action & QUEUE_ACTION) == QUEUE_REMOVE) { - /* - * FIXME: What to do? There might still be an - * object that has data in the read - * buffer and needs the map! - */ - } + int action = queueActionItems[i]; switch (action) { case QUEUE_ADD | QUEUE_READ: [_readObjects addObject: object]; - [self OF_addFileDescriptorForReading: fd]; + [self OF_addObjectForReading: object]; break; case QUEUE_ADD | QUEUE_WRITE: [_writeObjects addObject: object]; - [self OF_addFileDescriptorForWriting: fd]; + [self OF_addObjectForWriting: object]; break; case QUEUE_REMOVE | QUEUE_READ: - [self OF_removeFileDescriptorForReading: fd]; + [self OF_removeObjectForReading: object]; [removed addObject: object]; [_readObjects removeObjectIdenticalTo: object]; break; case QUEUE_REMOVE | QUEUE_WRITE: - [self OF_removeFileDescriptorForWriting: fd]; + [self OF_removeObjectForWriting: object]; [removed addObject: object]; [_writeObjects removeObjectIdenticalTo: object]; break; @@ -362,12 +325,11 @@ assert(0); } } [_queue removeAllObjects]; - [_queueInfo removeAllItems]; - [_queueFDs removeAllItems]; + [_queueActions removeAllItems]; } @finally { #ifdef OF_HAVE_THREADS [_mutex unlock]; #endif } Index: src/OFKernelEventObserver_epoll.m ================================================================== --- src/OFKernelEventObserver_epoll.m +++ src/OFKernelEventObserver_epoll.m @@ -26,10 +26,11 @@ #import "OFKernelEventObserver.h" #import "OFKernelEventObserver+Private.h" #import "OFKernelEventObserver_epoll.h" #import "OFMapTable.h" +#import "OFNull.h" #import "OFInitializationFailedException.h" #import "OFObserveFailedException.h" #define EVENTLIST_SIZE 64 @@ -40,10 +41,12 @@ - init { self = [super init]; @try { + struct epoll_event event; + #ifdef HAVE_EPOLL_CREATE1 if ((_epfd = epoll_create1(EPOLL_CLOEXEC)) == -1) @throw [OFInitializationFailedException exception]; #else int flags; @@ -57,11 +60,16 @@ _FDToEvents = [[OFMapTable alloc] initWithKeyFunctions: mapFunctions valueFunctions: mapFunctions]; - [self OF_addFileDescriptorForReading: _cancelFD[0]]; + memset(&event, 0, sizeof(event)); + event.events = EPOLLIN; + event.data.ptr = [OFNull null]; + + if (epoll_ctl(_epfd, EPOLL_CTL_ADD, _cancelFD[0], &event) == -1) + @throw [OFInitializationFailedException exception]; } @catch (id e) { [self release]; @throw e; } @@ -75,23 +83,23 @@ [_FDToEvents release]; [super dealloc]; } - -- (void)OF_addFileDescriptor: (int)fd - forEvents: (int)addEvents +- (void)OF_addObject: (id)object + fileDescriptor: (int)fd + events: (int)addEvents { intptr_t events; events = (intptr_t)[_FDToEvents valueForKey: (void*)(intptr_t)fd]; if (events == 0) { struct epoll_event event; memset(&event, 0, sizeof(event)); event.events = addEvents; - event.data.fd = fd; + event.data.ptr = object; if (epoll_ctl(_epfd, EPOLL_CTL_ADD, fd, &event) == -1) @throw [OFObserveFailedException exceptionWithObserver: self errNo: errno]; @@ -101,11 +109,11 @@ } else { struct epoll_event event; memset(&event, 0, sizeof(event)); event.events = (int)events | addEvents; - event.data.fd = fd; + event.data.ptr = object; if (epoll_ctl(_epfd, EPOLL_CTL_MOD, fd, &event) == -1) @throw [OFObserveFailedException exceptionWithObserver: self errNo: errno]; @@ -113,12 +121,13 @@ [_FDToEvents setValue: (void*)(events | addEvents) forKey: (void*)(intptr_t)fd]; } } -- (void)OF_removeFileDescriptor: (int)fd - forEvents: (int)removeEvents +- (void)OF_removeObject: (id)object + fileDescriptor: (int)fd + events: (int)removeEvents { intptr_t events; events = (intptr_t)[_FDToEvents valueForKey: (void*)(intptr_t)fd]; events &= ~removeEvents; @@ -133,11 +142,11 @@ } else { struct epoll_event event; memset(&event, 0, sizeof(event)); event.events = (int)events; - event.data.fd = fd; + event.data.ptr = object; if (epoll_ctl(_epfd, EPOLL_CTL_MOD, fd, &event) == -1) @throw [OFObserveFailedException exceptionWithObserver: self errNo: errno]; @@ -145,36 +154,41 @@ [_FDToEvents setValue: (void*)events forKey: (void*)(intptr_t)fd]; } } -- (void)OF_addFileDescriptorForReading: (int)fd -{ - [self OF_addFileDescriptor: fd - forEvents: EPOLLIN]; -} - -- (void)OF_addFileDescriptorForWriting: (int)fd -{ - [self OF_addFileDescriptor: fd - forEvents: EPOLLOUT]; -} - -- (void)OF_removeFileDescriptorForReading: (int)fd -{ - [self OF_removeFileDescriptor: fd - forEvents: EPOLLIN]; -} - -- (void)OF_removeFileDescriptorForWriting: (int)fd -{ - [self OF_removeFileDescriptor: fd - forEvents: EPOLLOUT]; +- (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]; } - (bool)observeForTimeInterval: (of_time_interval_t)timeInterval { + OFNull *nullObject = [OFNull null]; void *pool = objc_autoreleasePoolPush(); struct epoll_event eventList[EVENTLIST_SIZE]; int i, events, realEvents = 0; [self OF_processQueueAndStoreRemovedIn: nil]; @@ -195,11 +209,11 @@ if (events == 0) return false; for (i = 0; i < events; i++) { - if (eventList[i].data.fd == _cancelFD[0]) { + if (eventList[i].data.ptr == nullObject) { char buffer; assert(eventList[i].events == EPOLLIN); OF_ENSURE(read(_cancelFD[0], &buffer, 1) == 1); @@ -210,11 +224,11 @@ pool = objc_autoreleasePoolPush(); if ([_delegate respondsToSelector: @selector(objectIsReadyForReading:)]) [_delegate objectIsReadyForReading: - _FDToObject[eventList[i].data.fd]]; + eventList[i].data.ptr]; realEvents++; objc_autoreleasePoolPop(pool); } @@ -223,11 +237,11 @@ pool = objc_autoreleasePoolPush(); if ([_delegate respondsToSelector: @selector(objectIsReadyForWriting:)]) [_delegate objectIsReadyForWriting: - _FDToObject[eventList[i].data.fd]]; + eventList[i].data.ptr]; realEvents++; objc_autoreleasePoolPop(pool); } Index: src/OFKernelEventObserver_kqueue.m ================================================================== --- src/OFKernelEventObserver_kqueue.m +++ src/OFKernelEventObserver_kqueue.m @@ -43,10 +43,12 @@ - init { self = [super init]; @try { + struct kevent event; + #ifdef HAVE_KQUEUE1 if ((_kernelQueue = kqueue1(O_CLOEXEC)) == -1) @throw [OFInitializationFailedException exceptionWithClass: [self class]]; #else @@ -60,13 +62,14 @@ fcntl(_kernelQueue, F_SETFD, flags | FD_CLOEXEC); #endif _changeList = [[OFDataArray alloc] initWithItemSize: sizeof(struct kevent)]; - _removedArray = [[OFMutableArray alloc] init]; + EV_SET(&event, _cancelFD[0], EVFILT_READ, EV_ADD, 0, 0, 0); + [_changeList addItem: &event]; - [self OF_addFileDescriptorForReading: _cancelFD[0]]; + _removedArray = [[OFMutableArray alloc] init]; } @catch (id e) { [self release]; @throw e; } @@ -81,45 +84,69 @@ [_removedArray release]; [super dealloc]; } -- (void)OF_addFileDescriptorForReading: (int)fd +- (void)OF_addObjectForReading: (id)object { struct kevent event; if ([_changeList count] >= INT_MAX) @throw [OFOutOfRangeException exception]; - EV_SET(&event, fd, EVFILT_READ, EV_ADD, 0, 0, 0); + memset(&event, 0, sizeof(event)); + event.ident = [object fileDescriptorForReading]; + event.filter = EVFILT_READ; + event.flags = EV_ADD; +#ifndef __NetBSD__ + event.udata = object; +#else + event.udata = (intptr_t)object; +#endif + [_changeList addItem: &event]; } -- (void)OF_addFileDescriptorForWriting: (int)fd +- (void)OF_addObjectForWriting: (id)object { struct kevent event; if ([_changeList count] >= INT_MAX) @throw [OFOutOfRangeException exception]; - EV_SET(&event, fd, EVFILT_WRITE, EV_ADD, 0, 0, 0); + memset(&event, 0, sizeof(event)); + event.ident = [object fileDescriptorForWriting]; + event.filter = EVFILT_WRITE; + event.flags = EV_ADD; +#ifndef __NetBSD__ + event.udata = object; +#else + event.udata = (intptr_t)object; +#endif + [_changeList addItem: &event]; } -- (void)OF_removeFileDescriptorForReading: (int)fd +- (void)OF_removeObjectForReading: (id)object { struct kevent event; - EV_SET(&event, fd, EVFILT_READ, EV_DELETE, 0, 0, 0); + memset(&event, 0, sizeof(event)); + event.ident = [object fileDescriptorForReading]; + event.filter = EVFILT_READ; + event.flags = EV_DELETE; [_changeList addItem: &event]; } -- (void)OF_removeFileDescriptorForWriting: (int)fd +- (void)OF_removeObjectForWriting: (id)object { struct kevent event; - EV_SET(&event, fd, EVFILT_WRITE, EV_DELETE, 0, 0, 0); + memset(&event, 0, sizeof(event)); + event.ident = [object fileDescriptorForWriting]; + event.filter = EVFILT_WRITE; + event.flags = EV_DELETE; [_changeList addItem: &event]; } - (bool)observeForTimeInterval: (of_time_interval_t)timeInterval { @@ -173,17 +200,17 @@ switch (eventList[i].filter) { case EVFILT_READ: if ([_delegate respondsToSelector: @selector(objectIsReadyForReading:)]) [_delegate objectIsReadyForReading: - _FDToObject[eventList[i].ident]]; + (id)eventList[i].udata]; break; case EVFILT_WRITE: if ([_delegate respondsToSelector: @selector(objectIsReadyForWriting:)]) [_delegate objectIsReadyForWriting: - _FDToObject[eventList[i].ident]]; + (id)eventList[i].udata]; break; default: assert(0); } Index: src/OFKernelEventObserver_poll.h ================================================================== --- src/OFKernelEventObserver_poll.h +++ src/OFKernelEventObserver_poll.h @@ -19,7 +19,9 @@ @class OFDataArray; @interface OFKernelEventObserver_poll: OFKernelEventObserver { OFDataArray *_FDs; + size_t _maxFD; + __unsafe_unretained id *_FDToObject; } @end Index: src/OFKernelEventObserver_poll.m ================================================================== --- src/OFKernelEventObserver_poll.m +++ src/OFKernelEventObserver_poll.m @@ -43,17 +43,19 @@ - init { self = [super init]; @try { - struct pollfd p = { 0, POLLIN, 0 }; + struct pollfd p = { _cancelFD[0], POLLIN, 0 }; _FDs = [[OFDataArray alloc] initWithItemSize: sizeof(struct pollfd)]; - - p.fd = _cancelFD[0]; [_FDs addItem: &p]; + + _maxFD = _cancelFD[0]; + _FDToObject = [self allocMemoryWithSize: sizeof(id) + count: _maxFD + 1]; } @catch (id e) { [self release]; @throw e; } @@ -65,12 +67,13 @@ [_FDs release]; [super dealloc]; } -- (void)OF_addFileDescriptor: (int)fd - withEvents: (short)events +- (void)OF_addObject: (id)object + fileDescriptor: (int)fd + events: (short)events { struct pollfd *FDs = [_FDs items]; size_t i, count = [_FDs count]; bool found = false; @@ -82,54 +85,73 @@ } } if (!found) { struct pollfd p = { fd, events, 0 }; + + if (fd > _maxFD) { + _maxFD = fd; + _FDToObject = [self resizeMemory: _FDToObject + size: sizeof(id) + count: _maxFD + 1]; + } + + _FDToObject[fd] = object; [_FDs addItem: &p]; } } -- (void)OF_removeFileDescriptor: (int)fd - withEvents: (short)events +- (void)OF_removeObject: (id)object + fileDescriptor: (int)fd + events: (short)events { struct pollfd *FDs = [_FDs items]; size_t i, nFDs = [_FDs count]; for (i = 0; i < nFDs; i++) { if (FDs[i].fd == fd) { FDs[i].events &= ~events; - if (FDs[i].events == 0) + if (FDs[i].events == 0) { + /* + * TODO: Remove from and resize _FDToObject, + * adjust _maxFD. + */ [_FDs removeItemAtIndex: i]; + } break; } } } -- (void)OF_addFileDescriptorForReading: (int)fd -{ - [self OF_addFileDescriptor: fd - withEvents: POLLIN]; -} - -- (void)OF_addFileDescriptorForWriting: (int)fd -{ - [self OF_addFileDescriptor: fd - withEvents: POLLOUT]; -} - -- (void)OF_removeFileDescriptorForReading: (int)fd -{ - [self OF_removeFileDescriptor: fd - withEvents: POLLIN]; -} - -- (void)OF_removeFileDescriptorForWriting: (int)fd -{ - [self OF_removeFileDescriptor: fd - withEvents: POLLOUT]; +- (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]; } - (bool)observeForTimeInterval: (of_time_interval_t)timeInterval { void *pool = objc_autoreleasePoolPush(); @@ -163,10 +185,13 @@ if (events == 0) return false; for (i = 0; i < nFDs; i++) { + if (FDs[i].fd > _maxFD) + @throw [OFOutOfRangeException exception]; + if (FDs[i].revents & POLLIN) { if (FDs[i].fd == _cancelFD[0]) { char buffer; OF_ENSURE(read(_cancelFD[0], &buffer, 1) == 1); Index: src/OFKernelEventObserver_select.h ================================================================== --- src/OFKernelEventObserver_select.h +++ src/OFKernelEventObserver_select.h @@ -28,7 +28,8 @@ #import "OFKernelEventObserver.h" @interface OFKernelEventObserver_select: OFKernelEventObserver { fd_set _readFDs, _writeFDs; + int _maxFD; } @end Index: src/OFKernelEventObserver_select.m ================================================================== --- src/OFKernelEventObserver_select.m +++ src/OFKernelEventObserver_select.m @@ -32,58 +32,89 @@ #import "OFKernelEventObserver.h" #import "OFKernelEventObserver+Private.h" #import "OFKernelEventObserver_select.h" #import "OFArray.h" +#import "OFInitializationFailedException.h" #import "OFObserveFailedException.h" #import "OFOutOfRangeException.h" #import "socket_helpers.h" @implementation OFKernelEventObserver_select - init { self = [super init]; + +#ifndef _WIN32 + if (_cancelFD[0] >= FD_SETSIZE) + @throw [OFInitializationFailedException exception]; +#endif FD_ZERO(&_readFDs); FD_ZERO(&_writeFDs); - FD_SET(_cancelFD[0], &_readFDs); + + _maxFD = _cancelFD[0]; return self; } -- (void)OF_addFileDescriptorForReading: (int)fd +- (void)OF_addObjectForReading: (id)object { + int fd = [object fileDescriptorForReading]; + + if (fd > INT_MAX - 1) + @throw [OFOutOfRangeException exception]; + #ifndef _WIN32 if (fd >= FD_SETSIZE) @throw [OFOutOfRangeException exception]; #endif + + if (fd > _maxFD) + _maxFD = fd; FD_SET(fd, &_readFDs); } -- (void)OF_addFileDescriptorForWriting: (int)fd +- (void)OF_addObjectForWriting: (id)object { + int fd = [object fileDescriptorForWriting]; + + if (fd > INT_MAX - 1) + @throw [OFOutOfRangeException exception]; + #ifndef _WIN32 if (fd >= FD_SETSIZE) @throw [OFOutOfRangeException exception]; #endif + + if (fd > _maxFD) + _maxFD = fd; FD_SET(fd, &_writeFDs); } -- (void)OF_removeFileDescriptorForReading: (int)fd +- (void)OF_removeObjectForReading: (id)object { + /* TODO: Adjust _maxFD */ + + int fd = [object fileDescriptorForReading]; + if (fd >= FD_SETSIZE) @throw [OFOutOfRangeException exception]; FD_CLR(fd, &_readFDs); } -- (void)OF_removeFileDescriptorForWriting: (int)fd +- (void)OF_removeObjectForWriting: (id)object { + /* TODO: Adjust _maxFD */ + + int fd = [object fileDescriptorForWriting]; + if (fd >= FD_SETSIZE) @throw [OFOutOfRangeException exception]; FD_CLR(fd, &_writeFDs); } @@ -126,11 +157,11 @@ #else timeout.tv_sec = (long)timeInterval; #endif timeout.tv_usec = (int)lrint((timeInterval - timeout.tv_sec) * 1000); - events = select((int)_maxFD + 1, &readFDs, &writeFDs, NULL, + events = select(_maxFD + 1, &readFDs, &writeFDs, NULL, (timeInterval != -1 ? &timeout : NULL)); if (events < 0) @throw [OFObserveFailedException exceptionWithObserver: self errNo: errno];