Index: src/OFRunLoop.m ================================================================== --- src/OFRunLoop.m +++ src/OFRunLoop.m @@ -672,11 +672,12 @@ if (nextTimer != nil) { double timeout = [nextTimer timeIntervalSinceNow]; if (timeout > 0) #ifdef OF_HAVE_SOCKETS - [_streamObserver observeWithTimeout: timeout]; + [_streamObserver + observeForTimeInterval: timeout]; #else [OFThread sleepForTimeInterval: timeout]; #endif } else { /* Index: src/OFStreamObserver.h ================================================================== --- src/OFStreamObserver.h +++ src/OFStreamObserver.h @@ -29,10 +29,11 @@ @class OFMutableDictionary; @class OFDataArray; #ifdef OF_HAVE_THREADS @class OFMutex; #endif +@class OFDate; /*! * @brief A protocol that needs to be implemented by delegates for * OFStreamObserver. */ @@ -172,14 +173,23 @@ /*! * @brief Observes all streams until an event happens on a stream or the * timeout is reached. * - * @param timeout The time to wait for an event, in seconds + * @param timeInterval The time to wait for an event, in seconds * @return A boolean whether events occurred during the timeinterval */ -- (bool)observeWithTimeout: (double)timeout; +- (bool)observeForTimeInterval: (double)timeInterval; + +/*! + * @brief Observes all streams until an event happens on a stream or the + * timeout is reached. + * + * @param date The until which to observe + * @return A boolean whether events occurred until the specified date + */ +- (bool)observeUntilDate: (OFDate*)date; /*! * @brief Cancels the currently blocking observe call. * * This is automatically done when a new stream is added or removed by another Index: src/OFStreamObserver.m ================================================================== --- src/OFStreamObserver.m +++ src/OFStreamObserver.m @@ -33,10 +33,11 @@ # import "OFTCPSocket.h" #endif #ifdef OF_HAVE_THREADS # import "OFMutex.h" #endif +#import "OFDate.h" #ifdef HAVE_KQUEUE # import "OFStreamObserver_kqueue.h" #endif #ifdef HAVE_POLL_H @@ -368,18 +369,23 @@ } } - (void)observe { - [self observeWithTimeout: -1]; + [self observeForTimeInterval: -1]; } -- (bool)observeWithTimeout: (double)timeout +- (bool)observeForTimeInterval: (double)timeInterval { [self doesNotRecognizeSelector: _cmd]; abort(); } + +- (bool)observeUntilDate: (OFDate*)date +{ + return [self observeForTimeInterval: [date timeIntervalSinceNow]]; +} - (void)cancel { #ifndef _WIN32 OF_ENSURE(write(_cancelFD[1], "", 1) > 0); Index: src/OFStreamObserver_kqueue.m ================================================================== --- src/OFStreamObserver_kqueue.m +++ src/OFStreamObserver_kqueue.m @@ -14,10 +14,11 @@ * file. */ #include "config.h" +#include #include #include #include @@ -103,19 +104,19 @@ EV_SET(&event, fd, EVFILT_WRITE, EV_DELETE, 0, 0, 0); [_changeList addItem: &event]; } -- (bool)observeWithTimeout: (double)timeout +- (bool)observeForTimeInterval: (double)timeInterval { void *pool = objc_autoreleasePoolPush(); - struct timespec timespec; + struct timespec timeout; struct kevent eventList[EVENTLIST_SIZE]; int i, events, realEvents = 0; - timespec.tv_sec = (time_t)timeout; - timespec.tv_nsec = (long)((timeout - timespec.tv_sec) * 1000000000); + timeout.tv_sec = (time_t)timeInterval; + timeout.tv_nsec = lrint((timeInterval - timeout.tv_sec) * 1000000000); [self OF_processQueue]; if ([self OF_processCache]) { objc_autoreleasePoolPop(pool); @@ -124,11 +125,11 @@ objc_autoreleasePoolPop(pool); events = kevent(_kernelQueue, [_changeList items], (int)[_changeList count], eventList, EVENTLIST_SIZE, - (timeout == -1 ? NULL : ×pec)); + (timeInterval == -1 ? NULL : &timeout)); if (events < 0) return false; [_changeList removeAllItems]; Index: src/OFStreamObserver_poll.m ================================================================== --- src/OFStreamObserver_poll.m +++ src/OFStreamObserver_poll.m @@ -118,11 +118,11 @@ { [self OF_removeFileDescriptor: fd withEvents: POLLOUT]; } -- (bool)observeWithTimeout: (double)timeout +- (bool)observeForTimeInterval: (double)timeInterval { void *pool = objc_autoreleasePoolPush(); struct pollfd *FDs; size_t i, nFDs, realEvents = 0; @@ -142,11 +142,11 @@ if (nFDs > OPEN_MAX) @throw [OFOutOfRangeException exceptionWithClass: [self class]]; #endif if (poll(FDs, (nfds_t)nFDs, - (int)(timeout != -1 ? timeout * 1000 : -1)) < 1) + (int)(timeInterval != -1 ? timeInterval * 1000 : -1)) < 1) return false; for (i = 0; i < nFDs; i++) { pool = objc_autoreleasePoolPush(); Index: src/OFStreamObserver_select.m ================================================================== --- src/OFStreamObserver_select.m +++ src/OFStreamObserver_select.m @@ -17,10 +17,11 @@ #include "config.h" #define __NO_EXT_QNX #include +#include #include #include #import "OFStreamObserver_select.h" @@ -69,18 +70,18 @@ if (!FD_ISSET(fd, &_readFDs)) FD_CLR(fd, &_exceptFDs); } -- (bool)observeWithTimeout: (double)timeout +- (bool)observeForTimeInterval: (double)timeInterval { void *pool = objc_autoreleasePoolPush(); OFStream **objects; fd_set readFDs; fd_set writeFDs; fd_set exceptFDs; - struct timeval time; + struct timeval timeout; size_t i, count, realEvents = 0; [self OF_processQueue]; if ([self OF_processCache]) { @@ -104,15 +105,15 @@ * We cast to int before assigning to tv_usec in order to avoid a * warning with Apple GCC on PPC. POSIX defines this as suseconds_t, * however, this is not available on Win32. As an int should always * satisfy the required range, we just cast to int. */ - time.tv_sec = (time_t)timeout; - time.tv_usec = (int)((timeout - time.tv_sec) * 1000); + timeout.tv_sec = (time_t)timeInterval; + timeout.tv_usec = (int)lrint((timeInterval - timeout.tv_sec) * 1000); if (select((int)_maxFD + 1, &readFDs, &writeFDs, &exceptFDs, - (timeout != -1 ? &time : NULL)) < 1) + (timeInterval != -1 ? &timeout : NULL)) < 1) return false; if (FD_ISSET(_cancelFD[0], &readFDs)) { char buffer; #ifndef _WIN32