-
-
Save alloy/5679340 to your computer and use it in GitHub Desktop.
- (void)mapConcurrent; | |
{ | |
NSArray *originals = self.listOfObjects; | |
NSUInteger count = originals.count; | |
NSMutableArray *collected = [[NSMutableArray alloc] initWithCapacity:count]; | |
dispatch_group_t workGroup = dispatch_group_create(); | |
dispatch_queue_t assignmentQueue = dispatch_queue_create("com.example.SerialAssignmentQueue", DISPATCH_QUEUE_SERIAL); | |
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); | |
for (NSUInteger i = 0; i < count; i++) { | |
dispatch_group_async(workGroup, assignmentQueue, ^{ | |
// First ensure the destination slot exists, otherwise we can't assign the | |
// slot by index later on. | |
[collected addObject:[NSNull null]]; | |
dispatch_group_async(workGroup, concurrentQueue, ^{ | |
id original = originals[i]; | |
id result = [original performWork]; | |
dispatch_group_async(workGroup, assignmentQueue, ^{ | |
collected[i] = result; | |
}); | |
}); | |
}); | |
} | |
dispatch_group_wait(workGroup, DISPATCH_TIME_FOREVER); | |
} |
...it doesn’t have to be sync and in order...
Ah right, I forgot about NSEnumerationConcurrent
.
-valueForKey:{,Path:}
on an array is essentially a map, so I thought why not have a concurrent equivalent, for convenience. Ignore the names, but the following two would be equivalent:
[array concurrentValueForKey:@"foo"];
[array concurrentMap:^(id item) {
return [item valueForKey:@"foo"];
}];
What are you thinking for the implementation of filter? Use dispatch_apply
to build a sparse array and then do a linear pass over the array to build a compact copy for supplying to NSArray
? Or something else?
@alloy It's interesting that on your machine, the semaphore locking was slower than using the serial queue. So hardware alone can impact which one is more performant.
-valueForKey:{,Path:}
on an array is essentially a map, so I thought why not have a concurrent equivalent, for convenience.
I’m not sure it’s really needed vs just using the block version directly. The other problem is that you can use all sorts of funky syntax in normal KVC collection key paths and I don’t know if that would be easy to support.
What are you thinking for the implementation of filter? Use
dispatch_apply
to build a sparse array and then do a linear pass over the array to build a compact copy for supplying toNSArray
? Or something else?
Yeah, something like that.
PS I’m gone this weekend, so don’t wait for me if you want to hack on this :)
It's interesting that on your machine, the semaphore locking was slower than using the serial queue. So hardware alone can impact which one is more performant.
I hadn’t even noticed that. I’ve run it few more times and it’s pretty consistent.
I’m not sure it’s really needed vs just using the block version directly. The other problem is that you can use all sorts of funky syntax in normal KVC collection key paths and I don’t know if that would be easy to support.
Good points. I think the universe is telling me something, this isn't the first "convenience" method I've suggested in the past couple weeks that had its issues.
PS I’m gone this weekend, so don’t wait for me if you want to hack on this :)
Have a good weekend then. I may spend some time on this diversion, we'll see how the weekend plays out.
I was mainly thinking
map
andfilter
.each
can already be done with-[NSArray enumerateObjectsWithOptions:usingBlock:]
andNSEnumerationConcurrent
, plus it doesn’t have to be sync like map and filter need to be.And then define those on
NSArray
,NSDictionary
, and possiblyNSSet
.What would
-valueForKey:{,Path:}
do?