From 16b09c5202f3dc07e4d1935c5cd0670d96d6c29f Mon Sep 17 00:00:00 2001 From: Richard Frith-MacDonald Date: Wed, 7 Oct 2015 13:54:54 +0000 Subject: [PATCH] add option for writing a whole block in one go git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/performance/trunk@39039 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 5 ++++ GSFIFO.h | 24 ++++++++++----- GSFIFO.m | 77 ++++++++++++++++++++++++++++++++++++++++++++++++ GSIOThreadPool.m | 2 +- 4 files changed, 100 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1fc524c..307e4bf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-10-07 Richard Frith-Macdonald + + * GSFIFO.m: Add method for writing a whole block of data to a FIFO + in one go. + 2015-07-29 Richard Frith-Macdonald * GSLinkedList.h: diff --git a/GSFIFO.h b/GSFIFO.h index 9dcc60b..9bccceb 100644 --- a/GSFIFO.h +++ b/GSFIFO.h @@ -184,7 +184,7 @@ * time intervals found boundaries of bands into which to categorise wait * time stats. Any wait whose duration is less than the interval specified * in the Nth element is counted in the stat's for the Nth band. - * If this is nil, a default set of bundaries is used. If it is an empty + * If this is nil, a default set of boundaries is used. If it is an empty * array then no time based stats are recorded.
* The name string is a unique identifier for the receiver and is used when * printing diagnostics and statistics. If an instance with the same name @@ -221,13 +221,23 @@ */ - (id) initWithName: (NSString*)n; +/** Writes exactly count items from buf into the FIFO, blocking if + * necessary until there is space for the entire write.
+ * Raises an exception if the FIFO is configured with a timeout and it is + * exceeded, or if the count is greater than the FIFO size, or if the + * FIFO was not configured for multi producer or multi consumer use.
+ * If rtn is YES, the method treats the buffer as containing objects + * which are retained as they are added. + */ +- (void) putAll: (void**)buf count: (unsigned)count shouldRetain: (BOOL)rtn; + /** Writes up to count items from buf into the FIFO. * If block is YES, this blocks if necessary until at least one item * can be written, and raises an exception if the FIFO is configured * with a timeout and it is exceeded.
* Returns the number of items actually written. */ -- (unsigned) put: (void**)buf count: (unsigned)count shouldBlock: (BOOL)block; +- (unsigned) put: (void**)buf count: (unsigned)count shouldBlock: (BOOL)block; /** Writes up to count objects from buf into the FIFO, retaining each.
* If block is YES, this blocks if necessary until at least one object @@ -295,16 +305,16 @@ *
Calling this method does not remove the object from the * queue. */ -- (NSObject*)peekObject; +- (NSObject*) peekObject; -/** Attempts to retain an object while putting it into the FIFO, - * returning YES on success or NO if the FIFO is full.
+/** Attempts to put an object (or nil) into the FIFO, returning YES + * on success or NO if the FIFO is full.
* Implemented using -put:count:shouldBlock: */ - (BOOL) tryPut: (void*)item; -/** Attempts to put an object (or nil) into the FIFO, returning YES - * on success or NO if the FIFO is full.
+/** Attempts to retain an object while putting it into the FIFO, + * returning YES on success or NO if the FIFO is full.
* Implemented using -put:count:shouldBlock: */ - (BOOL) tryPutObject: (NSObject*)item; diff --git a/GSFIFO.m b/GSFIFO.m index 7877710..3eb4d7a 100644 --- a/GSFIFO.m +++ b/GSFIFO.m @@ -361,6 +361,83 @@ stats(NSTimeInterval ti, uint32_t max, NSTimeInterval *bounds, uint64_t *bands) return index; } +- (void) putAll: (void**)buf count: (unsigned)count shouldRetain: (BOOL)rtn +{ + NSTimeInterval ti; + unsigned index; + BOOL wasEmpty; + + NSAssert(nil != condition, NSGenericException); + NSAssert(count <= _capacity, NSInvalidArgumentException); + + [condition lock]; + if (_head - _tail < count) + { + if (_head - _tail == _capacity) + { + _putTryFailure++; + fullCount++; + } + + START + if (0 == timeout) + { + while (_head - _tail < count) + { + [condition wait]; + } + } + else + { + NSDate *d; + + d = [[NSDateClass alloc] + initWithTimeIntervalSinceNow: timeout / 1000.0f]; + while (_head - _tail < count) + { + if (NO == [condition waitUntilDate: d]) + { + [d release]; + ENDPUT + [condition broadcast]; + [condition unlock]; + [NSException raise: NSGenericException + format: @"Timeout waiting for space in FIFO"]; + } + } + [d release]; + } + ENDPUT + } + else + { + _putTrySuccess++; + } + + if (_head - _tail == 0) + { + wasEmpty = YES; + } + else + { + wasEmpty = NO; + } + for (index = 0; index < count; index++) + { + _items[_head % _capacity] = buf[index]; + _head++; + if (YES == rtn) + { + RETAIN((NSObject*)buf[index]); + } + } + if (YES == wasEmpty) + { + [condition broadcast]; + } + [condition unlock]; +} + - (void) dealloc { [classLock lock]; diff --git a/GSIOThreadPool.m b/GSIOThreadPool.m index 6ef9993..cee1f09 100644 --- a/GSIOThreadPool.m +++ b/GSIOThreadPool.m @@ -279,7 +279,7 @@ best(NSMutableArray *a) } #else [self release]; - NSLog(@"WARNING, your OSX system is too old to use GSIOthreadPool"); + NSLog(@"WARNING, your OSX system is too old to use GSIOThreadPool"); return nil; #endif return self;