Skip to content

Commit 8b97361

Browse files
committed
Add _InitPause & _InitResume states to safely invoke _performInitClosure.
1 parent 374ae1a commit 8b97361

File tree

1 file changed

+55
-8
lines changed

1 file changed

+55
-8
lines changed

SwiftTask/SwiftTask.swift

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,38 @@ public enum TaskState: String, StateType, Printable
3030
}
3131
}
3232

33-
public enum TaskEvent: String, StateEventType, Printable
33+
internal enum _TaskEvent: String, StateEventType, Printable
3434
{
3535
case Pause = "Pause"
3636
case Resume = "Resume"
3737
case Progress = "Progress"
3838
case Fulfill = "Fulfill"
3939
case Reject = "Reject" // also used in cancellation for simplicity
40+
41+
//
42+
// Private events to temporarily switch states (no event handlers)
43+
// without invoking `configure.resume()`,
44+
// i.e.
45+
//
46+
// `.Paused` (paused-init)
47+
// => `.Running` (only while invoking `_performInitClosure()`)
48+
// => `.Paused` (switch back)
49+
//
50+
// and finally by sending regular `.Resume` event:
51+
//
52+
// => `.Running` (again, but this time `configure.resume()` will be invoked)
53+
//
54+
case _InitResume = "_InitResume"
55+
case _InitPause = "_InitPause"
56+
4057
case Any = "Any"
4158

42-
public init(nilLiteral: Void)
59+
internal init(nilLiteral: Void)
4360
{
4461
self = Any
4562
}
4663

47-
public var description: String
64+
internal var description: String
4865
{
4966
return self.rawValue
5067
}
@@ -83,7 +100,7 @@ public class Task<Progress, Value, Error>: Printable
83100
internal typealias _RejectHandler = (ErrorInfo) -> Void
84101
internal typealias _InitClosure = (machine: Machine, progress: ProgressHandler, fulfill: FulFillHandler, _reject: _RejectHandler, configure: TaskConfiguration) -> Void
85102

86-
internal typealias Machine = StateMachine<TaskState, TaskEvent>
103+
internal typealias Machine = StateMachine<TaskState, _TaskEvent>
87104

88105
private var machine: Machine!
89106

@@ -245,6 +262,9 @@ public class Task<Progress, Value, Error>: Printable
245262
// setup state machine
246263
self.machine = Machine(state: initialState) {
247264

265+
$0.addRouteEvent(._InitPause, transitions: [.Running => .Paused])
266+
$0.addRouteEvent(._InitResume, transitions: [.Paused => .Running])
267+
248268
$0.addRouteEvent(.Pause, transitions: [.Running => .Paused])
249269
$0.addRouteEvent(.Resume, transitions: [.Paused => .Running])
250270
$0.addRouteEvent(.Progress, transitions: [.Running => .Running])
@@ -688,10 +708,37 @@ public class Task<Progress, Value, Error>: Printable
688708

689709
public func resume() -> Bool
690710
{
691-
// always try `_performInitClosure` only once on `resume()`
692-
// even when to-Resume-transition fails, e.g. already been fulfilled/rejected
693-
self._performInitClosure?()
694-
self._performInitClosure = nil
711+
//
712+
// Always try `_performInitClosure` only once on `resume()`
713+
// even when `.Pause => .Resume` transition fails, e.g. already been fulfilled/rejected.
714+
//
715+
// NOTE:
716+
// **`downstream._performInitClosure` should be invoked first before `downstream.machine <-! .Resume`**
717+
// to add upstream's progress/fulfill/reject handlers inside `downstream.initClosure()`
718+
// before their actual calls, which often happens
719+
// when downstream's `resume()` is configured to call upstream's `resume()`
720+
// which eventually calls `upstream._performInitClosure` and thus actual event handlers.
721+
//
722+
if (self._performInitClosure != nil) {
723+
724+
let isPaused = self.machine.state == .Paused
725+
726+
//
727+
// Temporarily switch to `.Running` without invoking `configure.resume()`.
728+
// This allows paused-inited-task to safely call progress/fulfill/reject handlers
729+
// inside its `initClosure` *immediately*.
730+
//
731+
if isPaused {
732+
self.machine <-! ._InitResume
733+
}
734+
735+
self._performInitClosure?()
736+
self._performInitClosure = nil
737+
738+
if isPaused {
739+
self.machine <-! ._InitPause // switch back
740+
}
741+
}
695742

696743
return self.machine <-! .Resume
697744
}

0 commit comments

Comments
 (0)