@@ -57,7 +57,7 @@ public class TaskConfiguration
57
57
}
58
58
}
59
59
60
- public class Task < Progress, Value, Error> : Printable
60
+ public class Task < Progress, Value, Error> : Cancellable , Printable
61
61
{
62
62
public typealias ProgressTuple = ( oldProgress: Progress ? , newProgress: Progress )
63
63
public typealias ErrorInfo = ( error: Error ? , isCancelled: Bool )
@@ -213,7 +213,8 @@ public class Task<Progress, Value, Error>: Printable
213
213
internal func setup( #weakified: Bool, paused: Bool, _initClosure: _InitClosure)
214
214
{
215
215
// #if DEBUG
216
- // println("[init] \(self.name)")
216
+ // let addr = String(format: "%p", unsafeAddressOf(self))
217
+ // NSLog("[init] \(self.name) \(addr)")
217
218
// #endif
218
219
219
220
self . _initClosure = _initClosure
@@ -287,7 +288,8 @@ public class Task<Progress, Value, Error>: Printable
287
288
deinit
288
289
{
289
290
// #if DEBUG
290
- // println("[deinit] \(self.name)")
291
+ // let addr = String(format: "%p", unsafeAddressOf(self))
292
+ // NSLog("[deinit] \(self.name) \(addr)")
291
293
// #endif
292
294
293
295
// cancel in case machine is still running
@@ -355,31 +357,62 @@ public class Task<Progress, Value, Error>: Printable
355
357
///
356
358
public func progress( progressClosure: ProgressTuple -> Void ) -> Task
357
359
{
358
- self . _machine. addProgressTupleHandler ( progressClosure)
360
+ var dummyCanceller : Canceller ? = nil
361
+ return self . progress ( & dummyCanceller, progressClosure)
362
+ }
363
+
364
+ public func progress< C: Canceller > ( inout canceller: C ? , _ progressClosure: ProgressTuple -> Void ) -> Task
365
+ {
366
+ var token : _HandlerToken ? = nil
367
+ self . _machine. addProgressTupleHandler ( & token, progressClosure)
368
+
369
+ canceller = C { [ weak self] in
370
+ self ? . _machine. removeProgressTupleHandler ( token)
371
+ }
359
372
360
373
return self
361
374
}
362
375
363
376
///
364
- /// then (fulfilled & rejected) + closure returning value
377
+ /// then (fulfilled & rejected) + closure returning **value**
378
+ /// (a.k.a. `map` in functional programming term)
365
379
///
366
380
/// - e.g. task.then { value, errorInfo -> NextValueType in ... }
367
381
///
368
382
public func then< Value2> ( thenClosure: ( Value ? , ErrorInfo ? ) -> Value2 ) -> Task < Progress , Value2 , Error >
369
383
{
370
- return self . then { ( value: Value ? , errorInfo: ErrorInfo ? ) -> Task < Progress , Value2 , Error > in
384
+ var dummyCanceller : Canceller ? = nil
385
+ return self . then ( & dummyCanceller, thenClosure)
386
+ }
387
+
388
+ public func then< Value2, C: Canceller > ( inout canceller: C ? , _ thenClosure: ( Value ? , ErrorInfo ? ) -> Value2 ) -> Task < Progress , Value2 , Error >
389
+ {
390
+ return self . then ( & canceller) { ( value: Value ? , errorInfo: ErrorInfo ? ) -> Task < Progress , Value2 , Error > in
371
391
return Task < Progress , Value2 , Error > ( value: thenClosure ( value, errorInfo) )
372
392
}
373
393
}
374
394
375
395
///
376
- /// then (fulfilled & rejected) + closure returning task
396
+ /// then (fulfilled & rejected) + closure returning **task**
397
+ /// (a.k.a. `flatMap` in functional programming term)
377
398
///
378
399
/// - e.g. task.then { value, errorInfo -> NextTaskType in ... }
379
400
///
380
401
public func then< Progress2, Value2> ( thenClosure: ( Value ? , ErrorInfo ? ) -> Task < Progress2 , Value2 , Error > ) -> Task < Progress2 , Value2 , Error >
381
402
{
382
- return Task < Progress2 , Value2 , Error > { [ unowned self] newMachine, progress, fulfill, _reject, configure in
403
+ var dummyCanceller : Canceller ? = nil
404
+ return self . then ( & dummyCanceller, thenClosure)
405
+ }
406
+
407
+ //
408
+ // NOTE: then-canceller is a shorthand of `task.cancel(nil)`, i.e. these two are the same:
409
+ //
410
+ // - `let canceller = Canceller(); task1.then(&canceller) {...}; canceller.cancel();`
411
+ // - `let task2 = task1.then {...}; task2.cancel();`
412
+ //
413
+ public func then< Progress2, Value2, C: Canceller > ( inout canceller: C ? , _ thenClosure: ( Value ? , ErrorInfo ? ) -> Task < Progress2 , Value2 , Error > ) -> Task < Progress2 , Value2 , Error >
414
+ {
415
+ return Task < Progress2 , Value2 , Error > { [ unowned self, weak canceller] newMachine, progress, fulfill, _reject, configure in
383
416
384
417
//
385
418
// NOTE:
@@ -389,8 +422,8 @@ public class Task<Progress, Value, Error>: Printable
389
422
// This is especially important for ReactKit's `deinitSignal` behavior.
390
423
//
391
424
let selfMachine = self . _machine
392
-
393
- self . _then {
425
+
426
+ self . _then ( & canceller ) {
394
427
let innerTask = thenClosure ( selfMachine. value, selfMachine. errorInfo)
395
428
_bindInnerTask ( innerTask, newMachine, progress, fulfill, _reject, configure)
396
429
}
@@ -399,41 +432,58 @@ public class Task<Progress, Value, Error>: Printable
399
432
}
400
433
401
434
/// invokes `completionHandler` "now" or "in the future"
402
- private func _then( completionHandler: Void -> Void )
435
+ private func _then< C : Canceller > ( inout canceller : C ? , _ completionHandler: Void -> Void )
403
436
{
404
437
switch self . state {
405
438
case . Fulfilled, . Rejected, . Cancelled:
406
439
completionHandler ( )
407
440
default :
408
- self . _machine. addCompletionHandler ( completionHandler)
441
+ var token : _HandlerToken ? = nil
442
+ self . _machine. addCompletionHandler ( & token, completionHandler)
443
+
444
+ canceller = C { [ weak self] in
445
+ self ? . _machine. removeCompletionHandler ( token)
446
+ }
409
447
}
410
448
}
411
449
412
450
///
413
- /// success (fulfilled) + closure returning value
451
+ /// success (fulfilled) + closure returning ** value**
414
452
///
415
453
/// - e.g. task.success { value -> NextValueType in ... }
416
454
///
417
455
public func success< Value2> ( successClosure: Value -> Value2 ) -> Task < Progress , Value2 , Error >
418
456
{
419
- return self . success { ( value: Value ) -> Task < Progress , Value2 , Error > in
457
+ var dummyCanceller : Canceller ? = nil
458
+ return self . success ( & dummyCanceller, successClosure)
459
+ }
460
+
461
+ public func success< Value2, C: Canceller > ( inout canceller: C ? , _ successClosure: Value -> Value2 ) -> Task < Progress , Value2 , Error >
462
+ {
463
+ return self . success ( & canceller) { ( value: Value ) -> Task < Progress , Value2 , Error > in
420
464
return Task < Progress , Value2 , Error > ( value: successClosure ( value) )
421
465
}
422
466
}
423
467
424
468
///
425
- /// success (fulfilled) + closure returning task
469
+ /// success (fulfilled) + closure returning ** task**
426
470
///
427
471
/// - e.g. task.success { value -> NextTaskType in ... }
428
472
///
429
473
public func success< Progress2, Value2> ( successClosure: Value -> Task < Progress2 , Value2 , Error > ) -> Task < Progress2 , Value2 , Error >
474
+ {
475
+ var dummyCanceller : Canceller ? = nil
476
+ return self . success ( & dummyCanceller, successClosure)
477
+ }
478
+
479
+ public func success< Progress2, Value2, C: Canceller > ( inout canceller: C ? , _ successClosure: Value -> Task < Progress2 , Value2 , Error > ) -> Task < Progress2 , Value2 , Error >
430
480
{
431
481
return Task < Progress2 , Value2 , Error > { [ unowned self] newMachine, progress, fulfill, _reject, configure in
432
482
433
483
let selfMachine = self . _machine
434
484
435
485
// NOTE: using `self._then()` + `selfMachine` instead of `self.then()` will reduce Task allocation
436
- self . _then {
486
+ self . _then ( & canceller ) {
437
487
if let value = selfMachine. value {
438
488
let innerTask = successClosure ( value)
439
489
_bindInnerTask ( innerTask, newMachine, progress, fulfill, _reject, configure)
@@ -447,31 +497,43 @@ public class Task<Progress, Value, Error>: Printable
447
497
}
448
498
449
499
///
450
- /// failure (rejected) + closure returning value
500
+ /// failure (rejected or cancelled ) + closure returning ** value**
451
501
///
452
502
/// - e.g. task.failure { errorInfo -> NextValueType in ... }
453
503
/// - e.g. task.failure { error, isCancelled -> NextValueType in ... }
454
504
///
455
505
public func failure( failureClosure: ErrorInfo -> Value ) -> Task
456
506
{
457
- return self . failure { ( errorInfo: ErrorInfo ) -> Task in
507
+ var dummyCanceller : Canceller ? = nil
508
+ return self . failure ( & dummyCanceller, failureClosure)
509
+ }
510
+
511
+ public func failure< C: Canceller > ( inout canceller: C ? , _ failureClosure: ErrorInfo -> Value ) -> Task
512
+ {
513
+ return self . failure ( & canceller) { ( errorInfo: ErrorInfo ) -> Task in
458
514
return Task ( value: failureClosure ( errorInfo) )
459
515
}
460
516
}
461
517
462
518
///
463
- /// failure (rejected) + closure returning task
519
+ /// failure (rejected or cancelled ) + closure returning ** task**
464
520
///
465
521
/// - e.g. task.failure { errorInfo -> NextTaskType in ... }
466
522
/// - e.g. task.failure { error, isCancelled -> NextTaskType in ... }
467
523
///
468
524
public func failure< Progress2> ( failureClosure: ErrorInfo -> Task < Progress2 , Value , Error > ) -> Task < Progress2 , Value , Error >
525
+ {
526
+ var dummyCanceller : Canceller ? = nil
527
+ return self . failure ( & dummyCanceller, failureClosure)
528
+ }
529
+
530
+ public func failure< Progress2, C: Canceller > ( inout canceller: C ? , _ failureClosure: ErrorInfo -> Task < Progress2 , Value , Error > ) -> Task < Progress2 , Value , Error >
469
531
{
470
532
return Task < Progress2 , Value , Error > { [ unowned self] newMachine, progress, fulfill, _reject, configure in
471
533
472
534
let selfMachine = self . _machine
473
535
474
- self . _then {
536
+ self . _then ( & canceller ) {
475
537
if let value = selfMachine. value {
476
538
fulfill ( value)
477
539
}
@@ -494,7 +556,18 @@ public class Task<Progress, Value, Error>: Printable
494
556
return self . _machine. handleResume ( )
495
557
}
496
558
497
- public func cancel( error: Error ? = nil ) -> Bool
559
+ //
560
+ // NOTE:
561
+ // To conform to `Cancellable`, this method is needed in replace of:
562
+ // - `public func cancel(error: Error? = nil) -> Bool`
563
+ // - `public func cancel(_ error: Error? = nil) -> Bool` (segfault in Swift 1.2)
564
+ //
565
+ public func cancel( ) -> Bool
566
+ {
567
+ return self . cancel ( error: nil )
568
+ }
569
+
570
+ public func cancel( #error: Error?) -> Bool
498
571
{
499
572
return self . _cancel ( error: error)
500
573
}
@@ -503,6 +576,7 @@ public class Task<Progress, Value, Error>: Printable
503
576
{
504
577
return self . _machine. handleCancel ( error: error)
505
578
}
579
+
506
580
}
507
581
508
582
// MARK: - Helper
0 commit comments