Skip to content

Instantly share code, notes, and snippets.

@alloy
Last active December 17, 2015 22:08
Show Gist options
  • Save alloy/5679340 to your computer and use it in GitHub Desktop.
Save alloy/5679340 to your computer and use it in GitHub Desktop.
Concurrent mapping with GCD.
- (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);
}
@alloy
Copy link
Author

alloy commented May 31, 2013

...it doesn’t have to be sync and in order...

@kastiglione
Copy link

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"];
}];

@kastiglione
Copy link

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?

@kastiglione
Copy link

@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.

@alloy
Copy link
Author

alloy commented May 31, 2013

-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 to NSArray? 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 :)

@alloy
Copy link
Author

alloy commented May 31, 2013

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.

@kastiglione
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment