@@ -30,14 +30,14 @@ struct TaskChain {
3030 /// that first task's `Root`.
3131 @objc ( BNRTaskRootProgress)
3232 private class Root : Progress {
33- /// Key for value of type `Root?` in `Thread.threadDictionary`.
34- static let threadKey = " _BNRTaskCurrentRoot "
33+ /// Key for value of type `[ Root] ?` in `Thread.threadDictionary`.
34+ static let threadKey = " _BNRTaskProgressStack "
3535
3636 /// Propogates the current Task chain for explicit composition during
3737 /// `Task.andThen`.
38- static var active : Root ? {
38+ static var activeStack : [ Root ] {
3939 get {
40- return Thread . current. threadDictionary [ threadKey] as? Root
40+ return Thread . current. threadDictionary [ threadKey] as? [ Root ] ?? [ ]
4141 }
4242 set {
4343 Thread . current. threadDictionary [ threadKey] = newValue
@@ -81,7 +81,7 @@ struct TaskChain {
8181 /// Locates or creates the root of a task chain, then generates any
8282 /// progress objects needed to represent `wrapped` in that chain.
8383 init < Wrapped: TaskProtocol > ( startingWith wrapped: Wrapped , using customProgress: Progress ? = nil , uponCancel cancellation: ( ( ) -> Void ) ? = nil ) {
84- if let root = Root . active {
84+ if let root = Root . activeStack . last {
8585 // We're inside `andThen` — `commitAndThen(with:)` will compose instead.
8686 self . root = root
8787 self . effectiveProgress = customProgress ?? . basicProgress( parent: nil , for: wrapped, uponCancel: cancellation)
@@ -148,27 +148,27 @@ struct TaskChain {
148148 /// progress and attach it to the root. If this next step provides custom
149149 /// progress, give it a 100x slice.
150150 func beginAndThen( ) {
151- Root . active = root
151+ Root . activeStack . append ( root)
152152 }
153153
154154 /// See `beginAndThen`.
155155 func commitAndThen< Wrapped: TaskProtocol > ( with wrapped: Wrapped ) {
156- if let task = wrapped as? Task < Wrapped . Success > , ! ( task . progress is Root ) {
156+ if let task = wrapped as? Task < Wrapped . Success > {
157157 let pendingUnitCount = task. progress. wasGeneratedByTask ? TaskChain . singleUnit : TaskChain . explicitChildUnitCount
158158 root. totalUnitCount += pendingUnitCount - TaskChain. singleUnit
159- root. adoptChild ( task. progress, withPendingUnitCount: pendingUnitCount)
159+ root. monitorChild ( task. progress, withPendingUnitCount: pendingUnitCount)
160160 } else {
161161 root. monitorCompletion ( of: wrapped, uponCancel: wrapped. cancel, withPendingUnitCount: TaskChain . singleUnit)
162162 }
163- Root . active = nil
163+ Root . activeStack . removeLast ( )
164164 }
165165
166166 /// When the `andThen` handler can't be run at all, mark the enqueued unit
167167 /// as complete anyway.
168168 func flushAndThen( ) {
169169 root. becomeCurrent ( withPendingUnitCount: TaskChain . singleUnit)
170170 root. resignCurrent ( )
171- Root . active = nil
171+ Root . activeStack . removeLast ( )
172172 }
173173}
174174#endif
0 commit comments