From 6f267319e380511a3d638eb467e1d704349bcd32 Mon Sep 17 00:00:00 2001 From: Niels Grewe Date: Fri, 17 Jul 2015 20:08:38 +0000 Subject: [PATCH] Optionally allow the caller to specify the time it wants to block on an empty FIFO. This supplements the existing method of having a timeout on the FIFO, and does not raise an excepion when the wait time is too long. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/performance/trunk@38814 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 6 ++++ GSFIFO.h | 23 +++++++++++++++ GSFIFO.m | 86 ++++++++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 102 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index c952204..9b6def9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2015-07-17 Niels Grewe + + * GSFIFO.m: Implement methods that allow waiting on an empty + FIFO for an arbitrary period of time, without raising an + exception. + 2015-07-16 Niels Grewe * GSFIFO.m: Implement -sizeInBytesExcluding: diff --git a/GSFIFO.h b/GSFIFO.h index c6b16f2..9dcc60b 100644 --- a/GSFIFO.h +++ b/GSFIFO.h @@ -118,6 +118,17 @@ */ - (unsigned) get: (void**)buf count: (unsigned)count shouldBlock: (BOOL)block; +/** + * Reads up to count items from the FIFO into the buf. If blocking is requested + * and a before date is specified, the operation blocks until the specified time + * and returns 0 if it could not read any items. The timeout configured for the + * FIFO still takes precedence. + */ +- (unsigned) get: (void**)buf + count: (unsigned)count + shouldBlock: (BOOL)block + before: (NSDate*)date; + /** Reads up to count objects from the FIFO (which must contain objects * or nil items) into buf and autoreleases them.
* If block is YES, this blocks if necessary until at least one object @@ -129,6 +140,18 @@ count: (unsigned)count shouldBlock: (BOOL)block; + +/** + * Reads up to count autoreleased objects from the FIFO into the buf. If blocking + * is requested and a before date is specified, the operation blocks until the + * specified time and returns 0 if it could not read any items. The timeout + * configured for the FIFO still takes precedence. + */ +- (unsigned) getObjects: (NSObject**)buf + count: (unsigned)count + shouldBlock: (BOOL)block + before: (NSDate*)date; + /** Gets the next item from the FIFO, blocking if necessary until an * item is available. Raises an exception if the FIFO is configured * with a timeout and it is exceeded.
diff --git a/GSFIFO.m b/GSFIFO.m index 4b12c5e..bf85f47 100644 --- a/GSFIFO.m +++ b/GSFIFO.m @@ -128,6 +128,7 @@ stats(NSTimeInterval ti, uint32_t max, NSTimeInterval *bounds, uint64_t *bands) - (unsigned) _cooperatingGet: (void**)buf count: (unsigned)count shouldBlock: (BOOL)block + before: (NSDate*)before { NSTimeInterval ti; unsigned index; @@ -145,7 +146,7 @@ stats(NSTimeInterval ti, uint32_t max, NSTimeInterval *bounds, uint64_t *bands) } START - if (0 == timeout) + if ((0 == timeout) && (before == nil)) { while (_head - _tail == 0) { @@ -155,22 +156,47 @@ stats(NSTimeInterval ti, uint32_t max, NSTimeInterval *bounds, uint64_t *bands) else { NSDate *d; - - d = [[NSDateClass alloc] - initWithTimeIntervalSinceNow: timeout / 1000.0f]; + NSDate *effective; + [before retain]; + if (timeout != 0) + { + d = [[NSDateClass alloc] + initWithTimeIntervalSinceNow: timeout / 1000.0f]; + } + if ((d != nil) && (before != nil)) + { + effective = [d earlierDate: before]; + } + else if (d != nil) + { + effective = d; + } + else + { + effective = before; + } while (_head - _tail == 0) { - if (NO == [condition waitUntilDate: d]) + if (NO == [condition waitUntilDate: effective]) { [d release]; + [before release]; ENDGET [condition broadcast]; [condition unlock]; - [NSException raise: NSGenericException - format: @"Timeout waiting for new data in FIFO"]; + if (before != effective) + { + [NSException raise: NSGenericException + format: @"Timeout waiting for new data in FIFO"]; + } + else + { + return 0; + } } } [d release]; + [before release]; ENDGET } } @@ -383,21 +409,28 @@ stats(NSTimeInterval ti, uint32_t max, NSTimeInterval *bounds, uint64_t *bands) fullCount]; } -- (unsigned) get: (void**)buf count: (unsigned)count shouldBlock: (BOOL)block +- (unsigned) get: (void**)buf + count: (unsigned)count + shouldBlock: (BOOL)block + before: (NSDate*)date + { unsigned index; NSTimeInterval ti; NSTimeInterval sum; + NSTimeInterval waitLength; uint32_t old; - uint32_t fib; - + uint32_t fib; if (0 == count) return 0; if (nil != condition) { - return [self _cooperatingGet: buf count: count shouldBlock: block]; + return [self _cooperatingGet: buf + count: count + shouldBlock: block + before: date]; } - + waitLength = [date timeIntervalSinceNow]; if (nil == getThread) { getThread = [NSThread currentThread]; @@ -434,6 +467,11 @@ stats(NSTimeInterval ti, uint32_t max, NSTimeInterval *bounds, uint64_t *bands) [NSException raise: NSGenericException format: @"Timeout waiting for new data in FIFO"]; } + else if (date != nil && sum > waitLength) + { + ENDGET + return 0; + } tmp = fib + old; old = fib; fib = tmp; @@ -454,14 +492,26 @@ stats(NSTimeInterval ti, uint32_t max, NSTimeInterval *bounds, uint64_t *bands) return index; } + +- (unsigned) get: (void**)buf count: (unsigned)count shouldBlock: (BOOL)block +{ + return [self get: buf count: count shouldBlock: block before: nil]; +} + + + - (unsigned) getObjects: (NSObject**)buf count: (unsigned)count shouldBlock: (BOOL)block + before: (NSDate*)date { unsigned result; unsigned index; - index = result = [self get: (void**)buf count: count shouldBlock: block]; + index = result = [self get: (void**)buf + count: count + shouldBlock: block + before: date]; while (index-- > 0) { [buf[index] autorelease]; @@ -469,6 +519,16 @@ stats(NSTimeInterval ti, uint32_t max, NSTimeInterval *bounds, uint64_t *bands) return result; } +- (unsigned) getObjects: (NSObject**)buf + count: (unsigned)count + shouldBlock: (BOOL)block +{ + return [self getObjects: buf + count: count + shouldBlock: block + before: nil]; +} + - (void*) get { void *item = 0;