Skip to content

Commit 6f15906

Browse files
authored
Merge pull request #439 from ReactiveCocoa/uischeduler-improvements
No cancel token if the action is immediately consumed by UIScheduler.
2 parents 5fce558 + 04b4ddf commit 6f15906

File tree

1 file changed

+28
-21
lines changed

1 file changed

+28
-21
lines changed

Sources/Scheduler.swift

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -136,37 +136,44 @@ public final class UIScheduler: Scheduler {
136136
/// begins.
137137
@discardableResult
138138
public func schedule(_ action: @escaping () -> Void) -> Disposable? {
139-
let disposable = AnyDisposable()
140-
let actionAndDecrement = {
141-
if !disposable.isDisposed {
139+
let positionInQueue = enqueue()
140+
141+
// If we're already running on the main queue, and there isn't work
142+
// already enqueued, we can skip scheduling and just execute directly.
143+
if positionInQueue == 1 && DispatchQueue.getSpecific(key: UIScheduler.dispatchSpecificKey) == UIScheduler.dispatchSpecificValue {
144+
action()
145+
dequeue()
146+
return nil
147+
} else {
148+
let disposable = AnyDisposable()
149+
150+
DispatchQueue.main.async {
151+
defer { self.dequeue() }
152+
guard !disposable.isDisposed else { return }
142153
action()
143154
}
144155

145-
#if os(Linux)
146-
self.queueLength.modify { $0 -= 1 }
147-
#else
148-
OSAtomicDecrement32(self.queueLength)
149-
#endif
156+
return disposable
150157
}
158+
}
151159

160+
private func dequeue() {
152161
#if os(Linux)
153-
let queued = self.queueLength.modify { value -> Int32 in
154-
value += 1
155-
return value
156-
}
162+
queueLength.modify { $0 -= 1 }
157163
#else
158-
let queued = OSAtomicIncrement32(queueLength)
164+
OSAtomicDecrement32(queueLength)
159165
#endif
166+
}
160167

161-
// If we're already running on the main queue, and there isn't work
162-
// already enqueued, we can skip scheduling and just execute directly.
163-
if queued == 1 && DispatchQueue.getSpecific(key: UIScheduler.dispatchSpecificKey) == UIScheduler.dispatchSpecificValue {
164-
actionAndDecrement()
165-
} else {
166-
DispatchQueue.main.async(execute: actionAndDecrement)
168+
private func enqueue() -> Int32 {
169+
#if os(Linux)
170+
return queueLength.modify { value -> Int32 in
171+
value += 1
172+
return value
167173
}
168-
169-
return disposable
174+
#else
175+
return OSAtomicIncrement32(queueLength)
176+
#endif
170177
}
171178
}
172179

0 commit comments

Comments
 (0)