@@ -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); }