-
Notifications
You must be signed in to change notification settings - Fork 0
17 — concurrentPerform
Instead of one chef chopping 1000 vegetables one at a time, split the pile across every available chef and let them all chop in parallel — but don't plate the dish until every chef is done.
DispatchQueue.concurrentPerform(iterations:) runs a closure iterations times in parallel across the thread pool, blocking the calling thread until every iteration completes. Best suited for CPU-bound, data-parallel work with no shared mutable state between iterations.
[vegetables] ──split──▶ chef1: chunk1
chef2: chunk2 ──▶ all done ──▶ continue
chef3: chunk3
DispatchQueue.concurrentPerform(iterations: vegetables.count) { index in
chop(vegetables[index]) // must be safe to run out of order, in parallel
}
print("All chopped, this line runs only after every iteration finishes")A TaskGroup iterating and awaiting all children achieves similar parallel iteration, but non-blocking (the calling task suspends instead of blocking a thread) and each child task is individually cancelable.
concurrentPerform is "split the pile across every chef, wait for all of them."
Unlike handing off physical vegetables, iterations that share mutable state can race with each other — concurrentPerform doesn't isolate iterations from one another.
Why is concurrentPerform a poor fit for iterations that depend on each other's results?