Added implementations of some of the new (10.6) NSArray methods that take blocks as arguments. These all use the new GSBlocks.h macros, so compile cleanly with GCC, but can be used by code compiled by clang.

Some of these implementations are not as efficient as they could be (especially the ones that take an NSIndexSet as the first argument).  They also don't yet support concurrent enumeration.  Apple implements these using Grand Central.  We could possibly have a background thread that we send these things to (or use GCD if libdispatch is available).  It's not worth spawning a new thread for them, except in exceptional circumstances (and, unfortunately, we can't easily tell how expensive a single iteration of a block is.  Possibly we could time one block invocation, and if it's longer than some threshold make it concurrent, but it's probably not worth the effort).



git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@29176 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
David Chisnall 2009-12-27 16:49:52 +00:00
parent 05f18160df
commit 34c77138fc
4 changed files with 213 additions and 2 deletions

View file

@ -1619,19 +1619,122 @@ compare(id elem1, id elem2, void* context)
return result;
}
- (void)enumerateObjectsUsingBlock: (GSEnumeratorBlock)aBlock
{
[self enumerateObjectsWithOptions: 0 usingBlock: aBlock];
}
- (void)enumerateObjectsWithOptions: (NSEnumerationOptions)opts
usingBlock: (GSEnumeratorBlock)aBlock
{
NSUInteger count = 0;
BOOL shouldStop = NO;
FOR_IN (id, obj, self)
id<NSFastEnumeration> enumerator = self;
/* If we are enumerating in reverse, use the reverse enumerator for fast
* enumeration. */
if (opts & NSEnumerationReverse)
{
enumerator = [self reverseObjectEnumerator];
}
FOR_IN (id, obj, enumerator)
CALL_BLOCK(aBlock, obj, count++, &shouldStop);
if (shouldStop)
{
return;
}
END_FOR_IN(self)
END_FOR_IN(enumerator)
}
- (void)enumerateObjectsAtIndexes: (NSIndexSet*)indexSet
options: (NSEnumerationOptions)opts
usingBlock: (GSEnumeratorBlock)block
{
[[self objectsAtIndexes: indexSet] enumerateObjectsWithOptions: opts
usingBlock: block];
}
- (NSIndexSet *)indexesOfObjectsWithOptions: (NSEnumerationOptions)opts
passingTest: (GSPredicateBlock)predicate
{
/* TODO: Concurrency. */
NSMutableIndexSet *set = [NSMutableIndexSet indexSet];
BOOL shouldStop = NO;
id<NSFastEnumeration> enumerator = self;
NSUInteger count = 0;
/* If we are enumerating in reverse, use the reverse enumerator for fast
* enumeration. */
if (opts & NSEnumerationReverse)
{
enumerator = [self reverseObjectEnumerator];
}
FOR_IN (id, obj, self)
if (CALL_BLOCK(predicate, obj, count, &shouldStop))
{
/* TODO: It would be more efficient to collect an NSRange and only
* pass it to the index set when CALL_BLOCK returned NO. */
[set addIndex: count];
}
if (shouldStop)
{
return set;
}
count++;
END_FOR_IN(self)
return set;
}
- (NSIndexSet*)indexesOfObjectsPassingTest: (GSPredicateBlock)predicate
{
return [self indexesOfObjectsWithOptions: 0 passingTest: predicate];
}
- (NSIndexSet*)indexesOfObjectsAtIndexes: (NSIndexSet*)indexSet
options: (NSEnumerationOptions)opts
passingTest: (GSPredicateBlock)predicate
{
return [[self objectsAtIndexes: indexSet] indexesOfObjectsWithOptions: opts
passingTest: predicate];
}
- (NSUInteger)indexOfObjectWithOptions: (NSEnumerationOptions)opts
passingTest: (GSPredicateBlock)predicate
{
/* TODO: Concurrency. */
id<NSFastEnumeration> enumerator = self;
BOOL shouldStop = NO;
NSUInteger count = 0;
/* If we are enumerating in reverse, use the reverse enumerator for fast
* enumeration. */
if (opts & NSEnumerationReverse)
{
enumerator = [self reverseObjectEnumerator];
}
FOR_IN (id, obj, self)
if (CALL_BLOCK(predicate, obj, count, &shouldStop))
{
return count;
}
if (shouldStop)
{
return NSNotFound;
}
count++;
END_FOR_IN(self)
return NSNotFound;
}
- (NSUInteger)indexOfObjectPassingTest: (GSPredicateBlock)predicate
{
return [self indexOfObjectWithOptions: 0 passingTest: predicate];
}
- (NSUInteger)indexOfObjectAtIndexes: (NSIndexSet*)indexSet
options: (NSEnumerationOptions)opts
passingTest: (GSPredicateBlock)predicate
{
return [[self objectsAtIndexes: indexSet] indexOfObjectWithOptions: 0
passingTest: predicate];
}
@end