<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Jul 7, 2016, at 11:03 AM, Pierre Habouzit <<a href="mailto:pierre@habouzit.net" class="">pierre@habouzit.net</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="font-family: SFMono-Light; font-size: 11px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class="">On Jul 7, 2016, at 10:01 AM, Karl via swift-corelibs-dev <<a href="mailto:swift-corelibs-dev@swift.org" class="">swift-corelibs-dev@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">Hi,<br class=""><br class="">I’d like to propose a change to the new GCD API; that DispatchWorkItems be retained by their groups (and in turn, for them to be retained by their queues). This allows for whoever created the work item to create a weak reference to it, as an indicator for whether or not it has finished executing.<br class=""></div></div></blockquote></div></div></blockquote><div><br class=""></div><div>Oh also, and that is a common misconception, groups have absolutely no ownership information so this “(… to be retained by their queues)” is not something that exists or is a thing.</div><div><br class=""></div><div>What does exist is that a group is never destroyed while it has unbalanced enter/leaves, and the DispatchWorkItem is definitely retained by any queue it has been async()ed to (you can async a single WorkItem to several places, however that precludes you from using .notify() or .wait()).</div><br class=""><blockquote type="cite" class=""><div class=""><div style="font-family: SFMono-Light; font-size: 11px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class=""><div class="">For example, let’s say I have some kind of class which manages a library of files. I want to have a refresh operation which runs on a background queue, enumerating the documents and perhaps even opening them and extracting some metadata:<br class=""><br class="">class DocumentLibrary {<br class=""><br class=""> weak var refreshOperation : DispatchWorkItem?<br class=""><br class=""> func refresh(force:Bool = false) {<br class=""><br class=""> If let ongoingOperation = refreshOperation {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-converted-space"> </span> if force == true {<br class=""> ongoingOperation.cancel() // force an update<br class=""> }<br class=""> else {<br class=""> return // already refreshing<br class=""> }<br class=""> }<br class=""><br class=""> refreshOperation = DispatchWorkItem(….) // processes the files, returns the results on the main queue<br class=""> DispatchQueue.global().async(refreshOperation)<br class=""> }<br class="">}<br class=""><br class="">This relies on the fact that weak references are thread-safe, and avoids the need for an explicit completion handler which nils the variable.<br class=""><br class="">Thoughts?<br class=""></div></div></blockquote></div><br class="" style="font-family: SFMono-Light; font-size: 11px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><div class="" style="font-family: SFMono-Light; font-size: 11px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">DispatchWorkItem.init() taking a group was a mistake and we are preparing an updated proposal to remove this and instead have a queue.async() overload that can take both a WorkItem and a group. The reason why is that the semantics of having a group attached to a DispatchWorkItem() is not useful, you most of the time want to enter() the group when the WorkItem is created, and have it consumed when it has run, but that not what the implementation does, it instead will enter the group at async() time.</div><div class="" style="font-family: SFMono-Light; font-size: 11px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: SFMono-Light; font-size: 11px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">However, if we changed the semantics to enter() at creation time, it would mean that the WorkItem could be asynced only once, which is a huge pitfall and design issue too.</div><div class="" style="font-family: SFMono-Light; font-size: 11px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: SFMono-Light; font-size: 11px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: SFMono-Light; font-size: 11px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">As far as your proposal goes:</div><div class="" style="font-family: SFMono-Light; font-size: 11px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">- dispatch groups are a single atomic counter and have no storage to own a reference on the WorkItem, changing this would dramatically change the performance profile of that existing API which is a non starter</div><div class="" style="font-family: SFMono-Light; font-size: 11px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">- anything could still have references on the DispatchWorkItem and using weak references to poll for completion is both a bad design (IMO) and fraught with peril</div><div class="" style="font-family: SFMono-Light; font-size: 11px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: SFMono-Light; font-size: 11px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">DispatchWorkItem come with .notify() and .wait() which are the things you should use for this. You should have a .notify() block that sets a boolean, on your class to track this.</div><div class="" style="font-family: SFMono-Light; font-size: 11px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: SFMono-Light; font-size: 11px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">Also using the global() queues is also fraught with another peril: thread explosion, but that’s probably outside of the scope of your feature request.</div></div></blockquote><div><br class=""></div></div><br class=""><div class=""><div class="">-Pierre</div></div><div class=""><br class=""></div></body></html>