Index: src/OFStreamObserver.h ================================================================== --- src/OFStreamObserver.h +++ src/OFStreamObserver.h @@ -177,12 +177,16 @@ * \return A boolean whether events occurred during the timeinterval */ - (BOOL)observeWithTimeout: (int)timeout; /// \cond internal +- (void)_addFileDescriptorForReading: (int)fd; +- (void)_addFileDescriptorForWriting: (int)fd; +- (void)_removeFileDescriptorForReading: (int)fd; +- (void)_removeFileDescriptorForWriting: (int)fd; - (void)_processQueue; - (BOOL)_processCache; /// \endcond @end @interface OFObject (OFStreamObserverDelegate) @end Index: src/OFStreamObserver_kqueue.h ================================================================== --- src/OFStreamObserver_kqueue.h +++ src/OFStreamObserver_kqueue.h @@ -13,13 +13,14 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #import "OFStreamObserver.h" + +@class OFDataArray; @interface OFStreamObserver_kqueue: OFStreamObserver { int kernelQueue; - int FDs; - struct kevent *eventList; + OFDataArray *changeList; } @end Index: src/OFStreamObserver_kqueue.m ================================================================== --- src/OFStreamObserver_kqueue.m +++ src/OFStreamObserver_kqueue.m @@ -15,10 +15,11 @@ */ #include "config.h" #include +#include #include #include #include @@ -28,14 +29,11 @@ #import "OFDataArray.h" #import "OFInitializationFailedException.h" #import "OFOutOfMemoryException.h" -@interface OFStreamObserver_kqueue (addEventForFileDescriptor) -- (void)_addEventForFileDescriptor: (int)fd - filter: (int16_t)filter; -@end +#define EVENTLIST_SIZE 64 @implementation OFStreamObserver_kqueue - init { self = [super init]; @@ -43,12 +41,14 @@ @try { if ((kernelQueue = kqueue()) == -1) @throw [OFInitializationFailedException newWithClass: isa]; - [self _addEventForFileDescriptor: cancelFD[0] - filter: EVFILT_READ]; + changeList = [[OFDataArray alloc] initWithItemSize: + sizeof(struct kevent)]; + + [self _addFileDescriptorForReading: cancelFD[0]]; } @catch (id e) { [self release]; @throw e; } @@ -56,95 +56,75 @@ } - (void)dealloc { close(kernelQueue); + [changeList release]; [super dealloc]; } -- (void)_addEventForFileDescriptor: (int)fd - filter: (int16_t)filter -{ - struct kevent event, result; - - eventList = [self resizeMemory: eventList - toNItems: FDs + 1 - ofSize: sizeof(struct kevent)]; - - EV_SET(&event, fd, filter, EV_ADD | EV_RECEIPT, 0, 0, 0); - - if (kevent(kernelQueue, &event, 1, &result, 1, NULL) != 1 || - result.data != 0) - /* FIXME: Find a better exception */ - @throw [OFInitializationFailedException newWithClass: isa]; - - FDs++; -} - -- (void)_removeEventForFileDescriptor: (int)fd - filter: (int16_t)filter -{ - struct kevent event, result; - - EV_SET(&event, fd, filter, EV_DELETE | EV_RECEIPT, 0, 0, 0); - - if (kevent(kernelQueue, &event, 1, &result, 1, NULL) != 1) - /* FIXME: Find a better exception */ - @throw [OFInitializationFailedException newWithClass: isa]; - - @try { - eventList = [self resizeMemory: eventList - toNItems: FDs - 1 - ofSize: sizeof(struct kevent)]; - } @catch (OFOutOfMemoryException *e) { - /* We don't care, as we only made it smaller */ - [e release]; - } - - FDs--; -} - - (void)_addFileDescriptorForReading: (int)fd { - [self _addEventForFileDescriptor: fd - filter: EVFILT_READ]; + struct kevent event; + + EV_SET(&event, fd, EVFILT_READ, EV_ADD, 0, 0, 0); + [changeList addItem: &event]; } - (void)_addFileDescriptorForWriting: (int)fd { - [self _addEventForFileDescriptor: fd - filter: EVFILT_WRITE]; + struct kevent event; + + EV_SET(&event, fd, EVFILT_WRITE, EV_ADD, 0, 0, 0); + [changeList addItem: &event]; } - (void)_removeFileDescriptorForReading: (int)fd { - [self _removeEventForFileDescriptor: fd - filter: EVFILT_READ]; + struct kevent event; + + EV_SET(&event, fd, EVFILT_READ, EV_DELETE, 0, 0, 0); + [changeList addItem: &event]; } - (void)_removeFileDescriptorForWriting: (int)fd { - [self _removeEventForFileDescriptor: fd - filter: EVFILT_WRITE]; + struct kevent event; + + EV_SET(&event, fd, EVFILT_WRITE, EV_DELETE, 0, 0, 0); + [changeList addItem: &event]; } - (BOOL)observeWithTimeout: (int)timeout { struct timespec timespec = { timeout, 0 }; + struct kevent eventList[EVENTLIST_SIZE]; int i, events; [self _processQueue]; if ([self _processCache]) return YES; - events = kevent(kernelQueue, NULL, 0, eventList, FDs, + events = kevent(kernelQueue, [changeList cArray], + (int)[changeList count], eventList, EVENTLIST_SIZE, (timeout == -1 ? NULL : ×pec)); - if (events == -1) - /* FIXME: Throw something */; + if (events == -1) { + switch (errno) { + case EINTR: + return NO; + case ENOMEM: + @throw [OFOutOfMemoryException newWithClass: isa]; + default: + assert(0); + } + } + + [changeList removeNItems: [changeList count]]; + if (events == 0) return NO; for (i = 0; i < events; i++) { if (eventList[i].ident == cancelFD[0]) { Index: src/exceptions/OFOutOfMemoryException.m ================================================================== --- src/exceptions/OFOutOfMemoryException.m +++ src/exceptions/OFOutOfMemoryException.m @@ -40,11 +40,11 @@ - (OFString*)description { if (description != nil) return description; - if (requestedSize) + if (requestedSize != 0) description = [[OFString alloc] initWithFormat: @"Could not allocate %zu bytes in class %@!", requestedSize, inClass]; else description = [[OFString alloc] initWithFormat: