@@ -30,10 +30,13 @@ #import "OFKernelEventObserver.h" #import "OFKernelEventObserver+Private.h" #import "OFKernelEventObserver_kqueue.h" #import "OFDataArray.h" #import "OFArray.h" +#ifdef OF_HAVE_THREADS +# import "OFMutex.h" +#endif #import "OFInitializationFailedException.h" #import "OFObserveFailedException.h" #import "OFOutOfRangeException.h" @@ -94,14 +97,27 @@ 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]; +#ifdef OF_HAVE_THREADS + [_mutex lock]; + @try { +#endif + [_readObjects addObject: object]; + + if (kevent(_kernelQueue, &event, 1, NULL, 0, NULL) != 0) { + [_readObjects removeObjectIdenticalTo: object]; + @throw [OFObserveFailedException + exceptionWithObserver: self + errNo: errno]; + } +#ifdef OF_HAVE_THREADS + } @finally { + [_mutex unlock]; + } +#endif } - (void)addObjectForWriting: (id )object { struct kevent event; @@ -114,14 +130,27 @@ 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]; +#ifdef OF_HAVE_THREADS + [_mutex lock]; + @try { +#endif + [_writeObjects addObject: object]; + + if (kevent(_kernelQueue, &event, 1, NULL, 0, NULL) != 0) { + [_writeObjects removeObjectIdenticalTo: object]; + @throw [OFObserveFailedException + exceptionWithObserver: self + errNo: errno]; + } +#ifdef OF_HAVE_THREADS + } @finally { + [_mutex unlock]; + } +#endif } - (void)removeObjectForReading: (id )object { struct kevent event; @@ -129,14 +158,25 @@ 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]; +#ifdef OF_HAVE_THREADS + [_mutex lock]; + @try { +#endif + if (kevent(_kernelQueue, &event, 1, NULL, 0, NULL) != 0) + @throw [OFObserveFailedException + exceptionWithObserver: self + errNo: errno]; + + [_readObjects removeObjectIdenticalTo: object]; +#ifdef OF_HAVE_THREADS + } @finally { + [_mutex unlock]; + } +#endif } - (void)removeObjectForWriting: (id )object { struct kevent event; @@ -144,14 +184,25 @@ 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]; +#ifdef OF_HAVE_THREADS + [_mutex lock]; + @try { +#endif + if (kevent(_kernelQueue, &event, 1, NULL, 0, NULL) != 0) + @throw [OFObserveFailedException + exceptionWithObserver: self + errNo: errno]; + + [_writeObjects removeObjectIdenticalTo: object]; +#ifdef OF_HAVE_THREADS + } @finally { + [_mutex unlock]; + } +#endif } - (void)observeForTimeInterval: (of_time_interval_t)timeInterval { void *pool = objc_autoreleasePoolPush();