<div dir="ltr"><div dir="auto" style="word-wrap:break-word"><br><div class="m_9146791611188767680AppleOriginalContents" style="direction:ltr"><blockquote type="cite"><div>On 24 Feb 2017, at 09:48, Brent Royal-Gordon &lt;<a href="mailto:brent@architechies.com" target="_blank">brent@architechies.com</a>&gt; wrote:</div><br class="m_9146791611188767680Apple-interchange-newline"><div><div><blockquote type="cite">On Feb 23, 2017, at 8:35 AM, Karl Wagner via swift-corelibs-dev &lt;<a href="mailto:swift-corelibs-dev@swift.org" target="_blank">swift-corelibs-dev@swift.org</a>&gt; wrote:<br><br>Would it be possible to make a cancelable version of DispatchQueue.<wbr>concurrentPerform, allowing you to abort any yet-to-be-scheduled blocks?<br><br>The use-case is for when you’re concurrently performing a job and one of them sets a flag or fails in a way which already defines the result. Further execution wouldn’t affect the outcome, so it would be nice if an operation could flag back to concurrentPerform that it doesn’t have to schedule any more jobs.<br><br>For a real-world example, see this concurrent RandomAccessCollection wrapper I was building: <a href="https://gist.github.com/karwa/43ae838809cc68d317003f2885c71572" target="_blank">https://gist.github.com/karwa/<wbr>43ae838809cc68d317003f2885c715<wbr>72</a><br></blockquote><br>Your example is:<br><br><br>    var _error: Error?<br>    DispatchQueue.<wbr>concurrentPerform(iterations: numericCast(count)) {<br>      do    { try body($0)   }<br>      catch { _error = error } // TODO: lock. Would be cool if we could cancel future iterations, too...<br>    }<br>    if let error = _error {<br>      try rescue(error)<br>    }<br><br>So how would cancelability be superior to saying this?<br><br>    var _error: Error?<br>    DispatchQueue.<wbr>concurrentPerform(iterations: numericCast(count)) {<br>      guard _error == nil else { return }<br>      do    { try body($0)   }<br>      catch { _error = error } // TODO: lock. Would be cool if we could cancel future iterations, too...<br>    }<br>    if let error = _error {<br>      try rescue(error)<br>    }<br><br>-- <br>Brent Royal-Gordon<br>Architechies<br><br></div></div><div><br></div></blockquote>That&#39;s a fair point, I could do that in order to skip the body. In general though, the size of the collection may be very large - we could be queuing up thousands of no-op blocks after the first element threw an error (or signalled a value, from a function like &quot;contains&quot;). It would be nice if we could propagate the fact that the outcome has already been determined up to Dispatch, which could then simply not bother to queue any more blocks.</div><div class="m_9146791611188767680AppleOriginalContents" style="direction:ltr"><br></div><div class="m_9146791611188767680AppleOriginalContents" style="">I&#39;ve kind-of worked around it by using a batched concurrentPerform for the methods where we can maybe expect early termination (such as contains).</div><br></div><div style="word-wrap:break-word">- Karl</div></div>