Index: src/OFStreamObserver.h ================================================================== --- src/OFStreamObserver.h +++ src/OFStreamObserver.h @@ -69,10 +69,12 @@ */ @interface OFStreamObserver: OFObject { OFMutableArray *readStreams; OFMutableArray *writeStreams; + OFStream **FDToStream; + size_t maxFD; OFMutableArray *queue, *queueInfo; id delegate; int cancelFD[2]; #ifdef _WIN32 struct sockaddr_in cancelAddr; @@ -164,11 +166,12 @@ * \return A boolean whether events occurred during the timeinterval */ - (BOOL)observeWithTimeout: (int)timeout; /// \cond internal +- (void)_processQueue; - (BOOL)_processCache; /// \endcond @end @interface OFObject (OFStreamObserverDelegate) @end Index: src/OFStreamObserver.m ================================================================== --- src/OFStreamObserver.m +++ src/OFStreamObserver.m @@ -49,10 +49,11 @@ QUEUE_ADD = 0, QUEUE_REMOVE = 1, QUEUE_READ = 0, QUEUE_WRITE = 2 }; +#define QUEUE_ACTION (QUEUE_ADD | QUEUE_REMOVE) @implementation OFStreamObserver + observer { return [[[self alloc] init] autorelease]; @@ -123,10 +124,15 @@ if (getsockname(cancelFD[0], (struct sockaddr*)&cancelAddr, &cancelAddrLen)) @throw [OFInitializationFailedException newWithClass: isa]; #endif + + maxFD = cancelFD[0]; + FDToStream = [self allocMemoryForNItems: maxFD + 1 + withSize: sizeof(OFStream*)]; + FDToStream[cancelFD[0]] = nil; } @catch (id e) { [self release]; @throw e; } @@ -234,10 +240,106 @@ sizeof(cancelAddr)) > 0); #endif [pool release]; } + +- (void)_addStreamToObserveForReading: (OFStream*)strea; +{ + @throw [OFNotImplementedException newWithClass: isa + selector: _cmd]; +} + +- (void)_addStreamToObserveForWriting: (OFStream*)stream +{ + @throw [OFNotImplementedException newWithClass: isa + selector: _cmd]; +} + +- (void)_removeStreamToObserveForReading: (OFStream*)stream +{ + @throw [OFNotImplementedException newWithClass: isa + selector: _cmd]; +} + +- (void)_removeStreamToObserveForWriting: (OFStream*)stream +{ + @throw [OFNotImplementedException newWithClass: isa + selector: _cmd]; +} + +- (void)_processQueue +{ + @synchronized (queue) { + OFStream **queueCArray = [queue cArray]; + OFNumber **queueInfoCArray = [queueInfo cArray]; + size_t i, count = [queue count]; + + for (i = 0; i < count; i++) { + int action = [queueInfoCArray[i] intValue]; + + if ((action & QUEUE_ACTION) == QUEUE_ADD) { + int fd = [queueCArray[i] fileDescriptor]; + + if (fd > maxFD) { + maxFD = fd; + FDToStream = [self + resizeMemory: FDToStream + toNItems: maxFD + 1 + withSize: sizeof(OFStream*)]; + } + + FDToStream[fd] = queueCArray[i]; + } + + if ((action & QUEUE_ACTION) == QUEUE_REMOVE) { + int fd = [queueCArray[i] fileDescriptor]; + + /* FIXME: Maybe downsize? */ + FDToStream[fd] = nil; + } + + switch (action) { + case QUEUE_ADD | QUEUE_READ: + [readStreams addObject: queueCArray[i]]; + + [self _addStreamToObserveForReading: + queueCArray[i]]; + + break; + case QUEUE_ADD | QUEUE_WRITE: + [writeStreams addObject: queueCArray[i]]; + + [self _addStreamToObserveForWriting: + queueCArray[i]]; + + break; + case QUEUE_REMOVE | QUEUE_READ: + [readStreams removeObjectIdenticalTo: + queueCArray[i]]; + + [self _removeStreamToObserveForReading: + queueCArray[i]]; + + break; + case QUEUE_REMOVE | QUEUE_WRITE: + [writeStreams removeObjectIdenticalTo: + queueCArray[i]]; + + [self _removeStreamToObserveForWriting: + queueCArray[i]]; + + break; + default: + assert(0); + } + } + + [queue removeNObjects: count]; + [queueInfo removeNObjects: count]; + } +} - (void)observe { [self observeWithTimeout: -1]; } Index: src/OFStreamObserver_poll.h ================================================================== --- src/OFStreamObserver_poll.h +++ src/OFStreamObserver_poll.h @@ -19,8 +19,7 @@ @class OFDataArray; @interface OFStreamObserver_poll: OFStreamObserver { OFDataArray *FDs; - OFMutableDictionary *FDToStream; } @end Index: src/OFStreamObserver_poll.m ================================================================== --- src/OFStreamObserver_poll.m +++ src/OFStreamObserver_poll.m @@ -30,17 +30,10 @@ #import "OFNumber.h" #import "OFAutoreleasePool.h" #import "OFOutOfRangeException.h" -enum { - QUEUE_ADD = 0, - QUEUE_REMOVE = 1, - QUEUE_READ = 0, - QUEUE_WRITE = 2 -}; - @implementation OFStreamObserver_poll - init { self = [super init]; @@ -47,11 +40,10 @@ @try { struct pollfd p = { 0, POLLIN, 0 }; FDs = [[OFDataArray alloc] initWithItemSize: sizeof(struct pollfd)]; - FDToStream = [[OFMutableDictionary alloc] init]; p.fd = cancelFD[0]; [FDs addItem: &p]; } @catch (id e) { [self release]; @@ -61,40 +53,34 @@ return self; } - (void)dealloc { - [FDToStream release]; [FDs release]; [super dealloc]; } - - (void)_addStream: (OFStream*)stream withEvents: (short)events { struct pollfd *FDsCArray = [FDs cArray]; size_t i, count = [FDs count]; - int fileDescriptor = [stream fileDescriptor]; + int fd = [stream fileDescriptor]; BOOL found = NO; for (i = 0; i < count; i++) { - if (FDsCArray[i].fd == fileDescriptor) { + if (FDsCArray[i].fd == fd) { FDsCArray[i].events |= events; found = YES; + break; } } if (!found) { - OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; - struct pollfd p = { fileDescriptor, events | POLLERR, 0 }; + struct pollfd p = { fd, events | POLLERR, 0 }; [FDs addItem: &p]; - [FDToStream setObject: stream - forKey: [OFNumber numberWithInt: - fileDescriptor]]; - [pool release]; } } - (void)_removeStream: (OFStream*)stream withEvents: (short)events @@ -103,75 +89,42 @@ size_t i, nFDs = [FDs count]; int fileDescriptor = [stream fileDescriptor]; for (i = 0; i < nFDs; i++) { if (FDsCArray[i].fd == fileDescriptor) { - OFAutoreleasePool *pool; - - FDsCArray[i].events &= ~events; - - if ((FDsCArray[i].events & ~POLLERR) != 0) - return; - - pool = [[OFAutoreleasePool alloc] init]; - - [FDs removeItemAtIndex: i]; - [FDToStream removeObjectForKey: - [OFNumber numberWithInt: fileDescriptor]]; - - [pool release]; - } - } -} - -- (void)_processQueue -{ - @synchronized (queue) { - OFStream **queueCArray = [queue cArray]; - OFNumber **queueInfoCArray = [queueInfo cArray]; - size_t i, count = [queue count]; - - for (i = 0; i < count; i++) { - switch ([queueInfoCArray[i] intValue]) { - case QUEUE_ADD | QUEUE_READ: - [readStreams addObject: queueCArray[i]]; - - [self _addStream: queueCArray[i] - withEvents: POLLIN]; - - break; - case QUEUE_ADD | QUEUE_WRITE: - [writeStreams addObject: queueCArray[i]]; - - [self _addStream: queueCArray[i] - withEvents: POLLOUT]; - - break; - case QUEUE_REMOVE | QUEUE_READ: - [readStreams removeObjectIdenticalTo: - queueCArray[i]]; - - [self _removeStream: queueCArray[i] - withEvents: POLLIN]; - - break; - case QUEUE_REMOVE | QUEUE_WRITE: - [writeStreams removeObjectIdenticalTo: - queueCArray[i]]; - - [self _removeStream: queueCArray[i] - withEvents: POLLOUT]; - - break; - default: - assert(0); - } - } - - [queue removeNObjects: count]; - [queueInfo removeNObjects: count]; - } + FDsCArray[i].events &= ~events; + + if ((FDsCArray[i].events & ~POLLERR) == 0) + [FDs removeItemAtIndex: i]; + + break; + } + } +} + +- (void)_addStreamToObserveForReading: (OFStream*)stream +{ + [self _addStream: stream + withEvents: POLLIN]; +} + +- (void)_addStreamToObserveForWriting: (OFStream*)stream +{ + [self _addStream: stream + withEvents: POLLOUT]; +} + +- (void)_removeStreamToObserveForReading: (OFStream*)stream +{ + [self _removeStream: stream + withEvents: POLLIN]; +} + +- (void)_removeStreamToObserveForWriting: (OFStream*)stream +{ + [self _removeStream: stream + withEvents: POLLOUT]; } - (BOOL)observeWithTimeout: (int)timeout { OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; @@ -193,13 +146,10 @@ if (poll(FDsCArray, (nfds_t)nFDs, timeout) < 1) return NO; for (i = 0; i < nFDs; i++) { - OFNumber *num; - OFStream *stream; - if (FDsCArray[i].revents & POLLIN) { if (FDsCArray[i].fd == cancelFD[0]) { char buffer; assert(read(cancelFD[0], &buffer, 1) > 0); @@ -206,27 +156,24 @@ FDsCArray[i].revents = 0; continue; } - num = [OFNumber numberWithInt: FDsCArray[i].fd]; - stream = [FDToStream objectForKey: num]; - [delegate streamDidBecomeReadyForReading: stream]; + [delegate streamDidBecomeReadyForReading: + FDToStream[FDsCArray[i].fd]]; [pool releaseObjects]; } if (FDsCArray[i].revents & POLLOUT) { - num = [OFNumber numberWithInt: FDsCArray[i].fd]; - stream = [FDToStream objectForKey: num]; - [delegate streamDidBecomeReadyForReading: stream]; + [delegate streamDidBecomeReadyForReading: + FDToStream[FDsCArray[i].fd]]; [pool releaseObjects]; } if (FDsCArray[i].revents & POLLERR) { - num = [OFNumber numberWithInt: FDsCArray[i].fd]; - stream = [FDToStream objectForKey: num]; - [delegate streamDidReceiveException: stream]; + [delegate streamDidReceiveException: + FDToStream[FDsCArray[i].fd]]; [pool releaseObjects]; } FDsCArray[i].revents = 0; } Index: src/OFStreamObserver_select.h ================================================================== --- src/OFStreamObserver_select.h +++ src/OFStreamObserver_select.h @@ -23,8 +23,7 @@ @interface OFStreamObserver_select: OFStreamObserver { fd_set readFDs; fd_set writeFDs; fd_set exceptFDs; - int nFDs; } @end Index: src/OFStreamObserver_select.m ================================================================== --- src/OFStreamObserver_select.m +++ src/OFStreamObserver_select.m @@ -26,111 +26,57 @@ #import "OFStream.h" #import "OFArray.h" #import "OFNumber.h" #import "OFAutoreleasePool.h" -#ifdef _WIN32 -# define close(sock) closesocket(sock) -#endif - -enum { - QUEUE_ADD = 0, - QUEUE_REMOVE = 1, - QUEUE_READ = 0, - QUEUE_WRITE = 2 -}; - @implementation OFStreamObserver_select - init { self = [super init]; FD_ZERO(&readFDs); FD_ZERO(&writeFDs); FD_SET(cancelFD[0], &readFDs); - nFDs = cancelFD[0] + 1; return self; } -- (void)_addStream: (OFStream*)stream - withFDSet: (fd_set*)FDSet -{ - OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; - int fileDescriptor = [stream fileDescriptor]; - - FD_SET(fileDescriptor, FDSet); - FD_SET(fileDescriptor, &exceptFDs); - - if (fileDescriptor >= nFDs) - nFDs = fileDescriptor + 1; - - [pool release]; -} - -- (void)_removeStream: (OFStream*)stream - withFDSet: (fd_set*)FDSet - otherFDSet: (fd_set*)otherFDSet -{ - int fileDescriptor = [stream fileDescriptor]; - - FD_CLR(fileDescriptor, FDSet); - - if (!FD_ISSET(fileDescriptor, otherFDSet)) - FD_CLR(fileDescriptor, &exceptFDs); -} - -- (void)_processQueue -{ - @synchronized (queue) { - OFStream **queueCArray = [queue cArray]; - OFNumber **queueInfoCArray = [queueInfo cArray]; - size_t i, count = [queue count]; - - for (i = 0; i < count; i++) { - switch ([queueInfoCArray[i] intValue]) { - case QUEUE_ADD | QUEUE_READ: - [readStreams addObject: queueCArray[i]]; - - [self _addStream: queueCArray[i] - withFDSet: &readFDs]; - - break; - case QUEUE_ADD | QUEUE_WRITE: - [writeStreams addObject: queueCArray[i]]; - - [self _addStream: queueCArray[i] - withFDSet: &writeFDs]; - - break; - case QUEUE_REMOVE | QUEUE_READ: - [readStreams removeObjectIdenticalTo: - queueCArray[i]]; - - [self _removeStream: queueCArray[i] - withFDSet: &readFDs - otherFDSet: &writeFDs]; - - break; - case QUEUE_REMOVE | QUEUE_WRITE: - [writeStreams removeObjectIdenticalTo: - queueCArray[i]]; - - [self _removeStream: queueCArray[i] - withFDSet: &writeFDs - otherFDSet: &readFDs]; - - break; - default: - assert(0); - } - } - - [queue removeNObjects: count]; - [queueInfo removeNObjects: count]; - } +- (void)_addStreamToObserveForReading: (OFStream*)stream +{ + int fd = [stream fileDescriptor]; + + FD_SET(fd, &readFDs); + FD_SET(fd, &exceptFDs); +} + +- (void)_addStreamToObserveForWriting: (OFStream*)stream +{ + int fd = [stream fileDescriptor]; + + FD_SET(fd, &writeFDs); + FD_SET(fd, &exceptFDs); +} + +- (void)_removeStreamToObserveForReading: (OFStream*)stream +{ + int fd = [stream fileDescriptor]; + + FD_CLR(fd, &readFDs); + + if (!FD_ISSET(fd, &writeFDs)) + FD_CLR(fd, &exceptFDs); +} + +- (void)_removeStreamToObserveForWriting: (OFStream*)stream +{ + int fd = [stream fileDescriptor]; + + FD_CLR(fd, &writeFDs); + + if (!FD_ISSET(fd, &readFDs)) + FD_CLR(fd, &exceptFDs); } - (BOOL)observeWithTimeout: (int)timeout { OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; @@ -157,11 +103,11 @@ # endif time.tv_sec = timeout / 1000; time.tv_usec = (timeout % 1000) * 1000; - if (select(nFDs, &readFDs_, &writeFDs_, &exceptFDs_, + if (select((int)maxFD + 1, &readFDs_, &writeFDs_, &exceptFDs_, (timeout != -1 ? &time : NULL)) < 1) return NO; if (FD_ISSET(cancelFD[0], &readFDs_)) { char buffer;