Skip to content

Commit de5c6f1

Browse files
committed
Add clone() & improve try() using recursive-call.
1 parent 9e20246 commit de5c6f1

File tree

1 file changed

+33
-40
lines changed

1 file changed

+33
-40
lines changed

SwiftTask/SwiftTask.swift

Lines changed: 33 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,11 @@ public class Task<Progress, Value, Error>: Printable
8989

9090
// store initial parameters for cloning task when using `try()`
9191
internal let _weakified: Bool
92-
internal var _initClosure: _InitClosure? // will be nil on fulfilled/rejected
92+
internal let _paused: Bool
93+
internal var _initClosure: _InitClosure! // retained throughout task's lifetime
9394

94-
/// wrapper closure for `_initClosure` to invoke only once when started `.Running`
95+
/// wrapper closure for `_initClosure` to invoke only once when started `.Running`,
96+
/// and will be set to `nil` afterward
9597
internal var _performInitClosure: (Void -> Void)?
9698

9799
/// progress value
@@ -149,6 +151,7 @@ public class Task<Progress, Value, Error>: Printable
149151
public init(weakified: Bool, paused: Bool, initClosure: InitClosure)
150152
{
151153
self._weakified = weakified
154+
self._paused = paused
152155

153156
let _initClosure: _InitClosure = { machine, progress, fulfill, _reject, configure in
154157
// NOTE: don't expose rejectHandler with ErrorInfo (isCancelled) for public init
@@ -219,16 +222,17 @@ public class Task<Progress, Value, Error>: Printable
219222
internal init(weakified: Bool = false, paused: Bool = false, _initClosure: _InitClosure)
220223
{
221224
self._weakified = weakified
225+
self._paused = paused
222226

223227
self.setup(weakified, paused: paused, _initClosure)
224228
}
225229

226230
internal func setup(weakified: Bool, paused: Bool, _initClosure: _InitClosure)
227-
{
231+
{
228232
// #if DEBUG
229-
// println("[init] \(self)")
233+
// println("[init] \(self.name)")
230234
// #endif
231-
235+
232236
let configuration = Configuration()
233237

234238
let initialState: TaskState = paused ? .Paused : .Running
@@ -277,12 +281,12 @@ public class Task<Progress, Value, Error>: Printable
277281

278282
// clear `_initClosure` & all StateMachine's handlers to prevent retain cycle
279283
$0.addEventHandler(.Fulfill, order: 255) { context in
280-
weakSelf?._initClosure = nil
284+
// weakSelf?._initClosure = nil // comment-out: let `task.deinit()` handle this
281285
weakSelf?._performInitClosure = nil
282286
weakSelf?.machine?.removeAllHandlers()
283287
}
284288
$0.addEventHandler(.Reject, order: 255) { context in
285-
weakSelf?._initClosure = nil
289+
// weakSelf?._initClosure = nil
286290
weakSelf?._performInitClosure = nil
287291
weakSelf?.machine?.removeAllHandlers()
288292
}
@@ -352,7 +356,7 @@ public class Task<Progress, Value, Error>: Printable
352356
deinit
353357
{
354358
// #if DEBUG
355-
// println("[deinit] \(self)")
359+
// println("[deinit] \(self.name)")
356360
// #endif
357361

358362
// cancel in case machine is still running
@@ -366,55 +370,44 @@ public class Task<Progress, Value, Error>: Printable
366370
return self
367371
}
368372

369-
/// Returns new task that is retryable for `tryCount-1` times.
370-
/// `task.try(n)` is conceptually equal to `task.failure(clonedTask1).failure(clonedTask2)...` with n-1 failure-able.
373+
/// Creates cloned task.
374+
public func clone() -> Task
375+
{
376+
return Task(weakified: self._weakified, paused: self._paused, _initClosure: self._initClosure)
377+
}
378+
379+
/// Returns new task that is retryable for `maxTryCount-1` times.
371380
public func try(maxTryCount: Int) -> Task
372381
{
373382
if maxTryCount < 2 { return self }
374383

375-
let weakified = self._weakified
376-
let initClosure = self._initClosure
377-
378-
if initClosure == nil { return self }
379-
380-
return Task { [weak self] machine, progress, fulfill, _reject, configure in
381-
382-
var chainedTasks = [self!]
383-
var nextTask: Task = self!
384-
385-
for i in 1...maxTryCount-1 {
386-
nextTask = nextTask.progress { _, progressValue in
387-
progress(progressValue)
388-
}.failure { _ -> Task in
389-
return Task(weakified: weakified, _initClosure: initClosure!) // create a clone-task when rejected
390-
}
391-
392-
chainedTasks += [nextTask]
393-
}
384+
return Task { machine, progress, fulfill, _reject, configure in
394385

395-
nextTask.progress { _, progressValue in
386+
let task = self.progress { _, progressValue in
396387
progress(progressValue)
388+
}.failure { [weak self] _ -> Task in
389+
return self!.clone().try(maxTryCount-1) // clone & try recursively
390+
}
391+
392+
task.progress { _, progressValue in
393+
progress(progressValue) // also receive progresses from clone-try-task
397394
}.success { value -> Void in
398395
fulfill(value)
399396
}.failure { errorInfo -> Void in
400397
_reject(errorInfo)
401398
}
402399

403400
configure.pause = {
404-
for task in chainedTasks {
405-
task.pause();
406-
}
401+
self.pause()
402+
task.pause()
407403
}
408404
configure.resume = {
409-
for task in chainedTasks {
410-
task.resume();
411-
}
405+
self.resume()
406+
task.resume()
412407
}
413408
configure.cancel = {
414-
// NOTE: use `reverse()` to cancel from downstream to upstream
415-
for task in chainedTasks.reverse() {
416-
task.cancel();
417-
}
409+
task.cancel() // cancel downstream first
410+
self.cancel()
418411
}
419412

420413
}.name("\(self.name)-try(\(maxTryCount))")

0 commit comments

Comments
 (0)