@@ -65,7 +65,18 @@ public class TaskConfiguration
65
65
}
66
66
}
67
67
68
- public class Task < Progress, Value, Error>
68
+ // abstract class for `weak _parentTask`
69
+ public class _Task < Error>
70
+ {
71
+ internal weak var _parentTask : _Task ?
72
+
73
+ public init ( ) { }
74
+ public func pause( ) -> Bool { return true }
75
+ public func resume( ) -> Bool { return true }
76
+ public func cancel( error: Error ? = nil ) -> Bool { return true }
77
+ }
78
+
79
+ public class Task < Progress, Value, Error> : _Task < Error >
69
80
{
70
81
public typealias ErrorInfo = ( error: Error ? , isCancelled: Bool )
71
82
@@ -81,7 +92,7 @@ public class Task<Progress, Value, Error>
81
92
public typealias InitClosure = ( progress: ProgressHandler , fulfill: FulFillHandler , reject: RejectHandler , configure: TaskConfiguration ) -> Void
82
93
83
94
internal typealias _RejectHandler = ( ErrorInfo ) -> Void
84
- internal typealias _InitClosure = ( progress: ProgressHandler , fulfill: FulFillHandler , _reject: _RejectHandler , configure: TaskConfiguration ) -> Void
95
+ internal typealias _InitClosure = ( machine : Machine , progress: ProgressHandler , fulfill: FulFillHandler , _reject: _RejectHandler , configure: TaskConfiguration ) -> Void
85
96
86
97
internal typealias Machine = StateMachine < TaskState , TaskEvent >
87
98
@@ -90,7 +101,7 @@ public class Task<Progress, Value, Error>
90
101
// store initial parameters for cloning task when using `try()`
91
102
internal let _weakified : Bool
92
103
internal var _initClosure : _InitClosure ? // will be nil on fulfilled/rejected
93
-
104
+
94
105
/// progress value
95
106
public internal( set) var progress : Progress ?
96
107
@@ -127,12 +138,13 @@ public class Task<Progress, Value, Error>
127
138
public init ( weakified: Bool , initClosure: InitClosure )
128
139
{
129
140
self . _weakified = weakified
130
- self . _initClosure = { ( progress, fulfill, _reject: _RejectHandler , configure) in
141
+ self . _initClosure = { machine , progress, fulfill, _reject, configure in
131
142
// NOTE: don't expose rejectHandler with ErrorInfo (isCancelled) for public init
132
143
initClosure ( progress: progress, fulfill: fulfill, reject: { ( error: Error ? ) in _reject ( ErrorInfo ( error: error, isCancelled: false ) ) } , configure: configure)
133
144
return
134
145
}
135
146
147
+ super. init ( )
136
148
self . setup ( weakified, self . _initClosure!)
137
149
}
138
150
@@ -175,14 +187,15 @@ public class Task<Progress, Value, Error>
175
187
self . _weakified = weakified
176
188
self . _initClosure = _initClosure
177
189
190
+ super. init ( )
178
191
self . setup ( weakified, _initClosure)
179
192
}
180
193
181
194
internal func setup( weakified: Bool , _initClosure: _InitClosure )
182
195
{
183
- #if DEBUG
184
- println ( " [init] \( self ) " )
185
- #endif
196
+ // #if DEBUG
197
+ // println("[init] \(self)")
198
+ // #endif
186
199
187
200
let configuration = Configuration ( )
188
201
@@ -227,14 +240,14 @@ public class Task<Progress, Value, Error>
227
240
configuration. clear ( )
228
241
}
229
242
230
- // clear `_initClosure` after fulfilled/rejected to prevent retain cycle
243
+ // clear `_initClosure` & all StateMachine's handlers to prevent retain cycle
231
244
$0. addEventHandler ( . Fulfill, order: 255 ) { context in
232
245
weakSelf? . _initClosure = nil
233
- return
246
+ weakSelf ? . machine ? . removeAllHandlers ( )
234
247
}
235
248
$0. addEventHandler ( . Reject, order: 255 ) { context in
236
249
weakSelf? . _initClosure = nil
237
- return
250
+ weakSelf ? . machine ? . removeAllHandlers ( )
238
251
}
239
252
240
253
}
@@ -281,7 +294,41 @@ public class Task<Progress, Value, Error>
281
294
}
282
295
}
283
296
284
- _initClosure ( progress: progressHandler, fulfill: fulfillHandler, _reject: rejectHandler, configure: configuration)
297
+ _initClosure ( machine: self . machine, progress: progressHandler, fulfill: fulfillHandler, _reject: rejectHandler, configure: configuration)
298
+
299
+ let userPauseClosure = configuration. pause
300
+ let userResumeClosure = configuration. resume
301
+ let userCancelClosure = configuration. cancel
302
+
303
+ // add parentTask-pause/resume/cancel functionalities after retrieving user-defined configuration
304
+ configuration. pause = { [ weak self] in
305
+ userPauseClosure ? ( )
306
+
307
+ var task : _Task ? = self
308
+ while let parentTask = task? . _parentTask {
309
+ parentTask. pause ( )
310
+ task = parentTask
311
+ }
312
+
313
+ }
314
+ configuration. resume = { [ weak self] in
315
+ userResumeClosure ? ( )
316
+
317
+ var task : _Task ? = self
318
+ while let parentTask = task? . _parentTask {
319
+ parentTask. resume ( )
320
+ task = parentTask
321
+ }
322
+ }
323
+ configuration. cancel = { [ weak self] in
324
+ userCancelClosure ? ( )
325
+
326
+ var task : _Task ? = self
327
+ while let parentTask = task? . _parentTask {
328
+ parentTask. cancel ( )
329
+ task = parentTask
330
+ }
331
+ }
285
332
286
333
}
287
334
@@ -339,9 +386,9 @@ public class Task<Progress, Value, Error>
339
386
/// then (fulfilled & rejected) + closure returning task
340
387
public func then< Progress2, Value2> ( thenClosure: ( Value ? , ErrorInfo ? ) -> Task < Progress2 , Value2 , Error > ) -> Task < Progress2 , Value2 , Error >
341
388
{
342
- let newTask = Task < Progress2 , Value2 , Error > { ( progress, fulfill, _reject: _RejectHandler , configure) in
389
+ let newTask = Task < Progress2 , Value2 , Error > { machine , progress, fulfill, _reject, configure in
343
390
344
- let bind = { ( value: Value ? , errorInfo: ErrorInfo ? ) -> Void in
391
+ let bind = { [ weak machine ] ( value: Value ? , errorInfo: ErrorInfo ? ) -> Void in
345
392
let innerTask = thenClosure ( value, errorInfo)
346
393
347
394
// NOTE: don't call `then` for innerTask, or recursive bindings may occur
@@ -352,6 +399,11 @@ public class Task<Progress, Value, Error>
352
399
case . Rejected:
353
400
_reject ( innerTask. errorInfo!)
354
401
default :
402
+ innerTask. machine. addEventHandler ( . Progress) { context in
403
+ if let ( _, progressValue) = context. userInfo as? Task < Progress2 , Value2 , Error > . ProgressTuple {
404
+ progress ( progressValue)
405
+ }
406
+ }
355
407
innerTask. machine. addEventHandler ( . Fulfill) { context in
356
408
if let value = context. userInfo as? Value2 {
357
409
fulfill ( value)
@@ -367,6 +419,14 @@ public class Task<Progress, Value, Error>
367
419
configure. pause = { innerTask. pause ( ) ; return }
368
420
configure. resume = { innerTask. resume ( ) ; return }
369
421
configure. cancel = { innerTask. cancel ( ) ; return }
422
+
423
+ // pause/cancel innerTask if descendant task is already paused/cancelled
424
+ if machine!. state == . Paused {
425
+ innerTask. pause ( )
426
+ }
427
+ else if machine!. state == . Cancelled {
428
+ innerTask. cancel ( )
429
+ }
370
430
}
371
431
372
432
switch self . machine. state {
@@ -375,6 +435,11 @@ public class Task<Progress, Value, Error>
375
435
case . Rejected:
376
436
bind ( nil , self . errorInfo!)
377
437
default :
438
+ self . machine. addEventHandler ( . Progress) { context in
439
+ if let ( _, progressValue) = context. userInfo as? Task < Progress2 , Value2 , Error > . ProgressTuple {
440
+ progress ( progressValue)
441
+ }
442
+ }
378
443
self . machine. addEventHandler ( . Fulfill) { context in
379
444
if let value = context. userInfo as? Value {
380
445
bind ( value, nil )
@@ -389,6 +454,8 @@ public class Task<Progress, Value, Error>
389
454
390
455
}
391
456
457
+ newTask. _parentTask = self
458
+
392
459
return newTask
393
460
}
394
461
@@ -403,12 +470,14 @@ public class Task<Progress, Value, Error>
403
470
/// success (fulfilled) + closure returning task
404
471
public func success< Progress2, Value2> ( successClosure: Value -> Task < Progress2 , Value2 , Error > ) -> Task < Progress2 , Value2 , Error >
405
472
{
406
- let newTask = Task < Progress2 , Value2 , Error > { ( progress, fulfill, _reject: _RejectHandler , configure) in
473
+ let newTask = Task < Progress2 , Value2 , Error > { machine , progress, fulfill, _reject, configure in
407
474
408
- let bind = { ( value: Value ) -> Void in
475
+ let bind = { [ weak machine ] ( value: Value ) -> Void in
409
476
let innerTask = successClosure ( value)
410
477
411
- innerTask. then { ( value: Value2 ? , errorInfo: ErrorInfo ? ) -> Void in
478
+ innerTask. progress { _, progressValue in
479
+ progress ( progressValue)
480
+ } . then { ( value: Value2 ? , errorInfo: ErrorInfo ? ) -> Void in
412
481
if let value = value {
413
482
fulfill ( value)
414
483
}
@@ -420,6 +489,14 @@ public class Task<Progress, Value, Error>
420
489
configure. pause = { innerTask. pause ( ) ; return }
421
490
configure. resume = { innerTask. resume ( ) ; return }
422
491
configure. cancel = { innerTask. cancel ( ) ; return }
492
+
493
+ // pause/cancel innerTask if descendant task is already paused/cancelled
494
+ if machine!. state == . Paused {
495
+ innerTask. pause ( )
496
+ }
497
+ else if machine!. state == . Cancelled {
498
+ innerTask. cancel ( )
499
+ }
423
500
}
424
501
425
502
switch self . machine. state {
@@ -428,6 +505,11 @@ public class Task<Progress, Value, Error>
428
505
case . Rejected:
429
506
_reject ( self . errorInfo!)
430
507
default :
508
+ self . machine. addEventHandler ( . Progress) { context in
509
+ if let ( _, progressValue) = context. userInfo as? Task < Progress2 , Value2 , Error > . ProgressTuple {
510
+ progress ( progressValue)
511
+ }
512
+ }
431
513
self . machine. addEventHandler ( . Fulfill) { context in
432
514
if let value = context. userInfo as? Value {
433
515
bind ( value)
@@ -442,6 +524,8 @@ public class Task<Progress, Value, Error>
442
524
443
525
}
444
526
527
+ newTask. _parentTask = self
528
+
445
529
return newTask
446
530
}
447
531
@@ -456,12 +540,14 @@ public class Task<Progress, Value, Error>
456
540
/// failure (rejected) + closure returning task
457
541
public func failure( failureClosure: ErrorInfo -> Task ) -> Task
458
542
{
459
- let newTask = Task { ( progress, fulfill, _reject: _RejectHandler , configure) in
543
+ let newTask = Task { machine , progress, fulfill, _reject, configure in
460
544
461
- let bind = { ( errorInfo: ErrorInfo ) -> Void in
545
+ let bind = { [ weak machine ] ( errorInfo: ErrorInfo ) -> Void in
462
546
let innerTask = failureClosure ( errorInfo)
463
547
464
- innerTask. then { ( value: Value ? , errorInfo: ErrorInfo ? ) -> Void in
548
+ innerTask. progress { _, progressValue in
549
+ progress ( progressValue)
550
+ } . then { ( value: Value ? , errorInfo: ErrorInfo ? ) -> Void in
465
551
if let value = value {
466
552
fulfill ( value)
467
553
}
@@ -472,7 +558,15 @@ public class Task<Progress, Value, Error>
472
558
473
559
configure. pause = { innerTask. pause ( ) ; return }
474
560
configure. resume = { innerTask. resume ( ) ; return }
475
- configure. cancel = { innerTask. cancel ( ) ; return }
561
+ configure. cancel = { innerTask. cancel ( ) ; return }
562
+
563
+ // pause/cancel innerTask if descendant task is already paused/cancelled
564
+ if machine!. state == . Paused {
565
+ innerTask. pause ( )
566
+ }
567
+ else if machine!. state == . Cancelled {
568
+ innerTask. cancel ( )
569
+ }
476
570
}
477
571
478
572
switch self . machine. state {
@@ -482,6 +576,11 @@ public class Task<Progress, Value, Error>
482
576
let errorInfo = self . errorInfo!
483
577
bind ( errorInfo)
484
578
default :
579
+ self . machine. addEventHandler ( . Progress) { context in
580
+ if let ( _, progressValue) = context. userInfo as? Task . ProgressTuple {
581
+ progress ( progressValue)
582
+ }
583
+ }
485
584
self . machine. addEventHandler ( . Fulfill) { context in
486
585
if let value = context. userInfo as? Value {
487
586
fulfill ( value)
@@ -496,20 +595,22 @@ public class Task<Progress, Value, Error>
496
595
497
596
}
498
597
598
+ newTask. _parentTask = self
599
+
499
600
return newTask
500
601
}
501
602
502
- public func pause( ) -> Bool
603
+ public override func pause( ) -> Bool
503
604
{
504
605
return self . machine <-! . Pause
505
606
}
506
607
507
- public func resume( ) -> Bool
608
+ public override func resume( ) -> Bool
508
609
{
509
610
return self . machine <-! . Resume
510
611
}
511
612
512
- public func cancel( error: Error ? = nil ) -> Bool
613
+ public override func cancel( error: Error ? = nil ) -> Bool
513
614
{
514
615
return self . _cancel ( error: error)
515
616
}
@@ -524,7 +625,7 @@ extension Task
524
625
{
525
626
public class func all( tasks: [ Task ] ) -> Task < BulkProgress , [ Value ] , Error >
526
627
{
527
- return Task < BulkProgress , [ Value ] , Error > { ( progress, fulfill, _reject: _RejectHandler , configure) in
628
+ return Task < BulkProgress , [ Value ] , Error > { machine , progress, fulfill, _reject, configure in
528
629
529
630
var completedCount = 0
530
631
let totalCount = tasks. count
@@ -570,7 +671,7 @@ extension Task
570
671
571
672
public class func any( tasks: [ Task ] ) -> Task
572
673
{
573
- return Task < Progress , Value , Error > { ( progress, fulfill, _reject: _RejectHandler , configure) in
674
+ return Task < Progress , Value , Error > { machine , progress, fulfill, _reject, configure in
574
675
575
676
var completedCount = 0
576
677
var rejectedCount = 0
@@ -615,7 +716,7 @@ extension Task
615
716
/// This new task will NEVER be internally rejected.
616
717
public class func some( tasks: [ Task ] ) -> Task < BulkProgress , [ Value ] , Error >
617
718
{
618
- return Task < BulkProgress , [ Value ] , Error > { ( progress, fulfill, _reject: _RejectHandler , configure) in
719
+ return Task < BulkProgress , [ Value ] , Error > { machine , progress, fulfill, _reject, configure in
619
720
620
721
var completedCount = 0
621
722
let totalCount = tasks. count
0 commit comments