RxSwift之scheduler
在之前阅读 RxSwift 源码过程中,总是和 scheduler 偶遇,这次我们来正式认识一下!
demo
Observable.of(1,2,3,4,5)
.observeOn(SerialDispatchQueueScheduler.init(internalSerialQueueName:"observeOnSerial"))
.subscribe{print("observeOn",$0,Thread.current)}
.disposed(by: disposeBag)
输出:
observeOn next(1) {number = 4, name = (null)}
observeOn next(2) {number = 4, name = (null)}
observeOn next(3) {number = 4, name = (null)}
observeOn next(4) {number = 4, name = (null)}
observeOn next(5) {number = 4, name = (null)}
observeOn completed {number = 4, name = (null)}
of函数
public static func of(_ elements: Element ...,
scheduler: ImmediateSchedulerType = CurrentThreadScheduler.instance) -> Observable {
return ObservableSequence(elements: elements, scheduler: scheduler)
}
ObservableSequence源序列
of(elements:,scheduler:)->Observable
函数通过给定的元素,创建了一个可观察序列ObservableSequence
,它是Producer
的子类,还有个 scheduler 参数默认值为当前线程调度者。在 demo 中就是主线程调度者。正是本片的主角scheduler
。这里默认的 scheduler 是CurrentThreadScheduler
实例,遵守ImmediateSchedulerType
协议。
final private class ObservableSequence: Producer {
fileprivate let _elements: Sequence
fileprivate let _scheduler: ImmediateSchedulerType
init(elements: Sequence, scheduler: ImmediateSchedulerType) {
self._elements = elements
self._scheduler = scheduler
}
override func run(_ observer: Observer, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where Observer.Element == Element {
let sink = ObservableSequenceSink(parent: self, observer: observer, cancel: cancel)
let subscription = sink.run()
return (sink: sink, subscription: subscription)
}
}
CurrentThreadScheduler当前线程调度者
public class CurrentThreadScheduler : ImmediateSchedulerType {
/// The singleton instance of the current thread scheduler.
public static let instance = CurrentThreadScheduler()
}
- 创建
Producer
的子类ObservableSequence
ObservableSequence
两个属性:
- _elements: Sequence(N个元素)
- _scheduler: ImmediateSchedulerType(当前线程调度者
CurrentThreadScheduler
)
observeOn函数
public func observeOn(_ scheduler: ImmediateSchedulerType) -> Observable {
if let scheduler = scheduler as? SerialDispatchQueueScheduler {
return ObserveOnSerialDispatchQueue(source: self.asObservable(), scheduler: scheduler)
} else {
return ObserveOn(source: self.asObservable(), scheduler: scheduler)
}
}
ObservableSequence
在调用observeOn
时,根据 scheduler 是串行还是并行去创建不同的类型的中间序列。我们先关注串行队列来学习。这里是创建的ObserveOnSerialDispatchQueue
中间序列。
ObserveOnSerialDispatchQueue中间序列
final private class ObserveOnSerialDispatchQueue: Producer {
let scheduler: SerialDispatchQueueScheduler
let source: Observable
init(source: Observable, scheduler: SerialDispatchQueueScheduler) {
self.scheduler = scheduler
self.source = source
}
override func run(_ observer: Observer, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where Observer.Element == Element {
let sink = ObserveOnSerialDispatchQueueSink(scheduler: self.scheduler,
observer: observer,
cancel: cancel)
let subscription = self.source.subscribe(sink)
return (sink: sink, subscription: subscription)
}
}
中间序列初始化时保存了源序列和串行队列。
SerialDispatchQueueScheduler串行调度者
public class SerialDispatchQueueScheduler : SchedulerType {
let configuration: DispatchQueueConfiguration
init(serialQueue: DispatchQueue, leeway: DispatchTimeInterval = DispatchTimeInterval.nanoseconds(0)) {
self.configuration = DispatchQueueConfiguration(queue: serialQueue, leeway: leeway)
}
public convenience init(internalSerialQueueName: String, serialQueueConfiguration: ((DispatchQueue) -> Void)? = nil, leeway: DispatchTimeInterval = DispatchTimeInterval.nanoseconds(0)) {
let queue = DispatchQueue(label: internalSerialQueueName, attributes: [])
serialQueueConfiguration?(queue)
self.init(serialQueue: queue, leeway: leeway)
}
}
这里贴出串行队列调度者的代码,可以和前面of函数
部分相呼应。可以清楚的看到,序列、调度者,还有订阅后产生的观察者、管道都是两套的。
- 中间序列
ObserveOnSerialDispatchQueue
两个属性:
- scheduler: SerialDispatchQueueScheduler(串行调度者,
SerialDispatchQueueScheduler
)- source: Observable
(源序列, ObservableSequence
)
subscribe函数
好戏开始!随着 subscribe 的调用,在创建匿名观察者后会走父类 Producer 的 subscribe 中:
override func subscribe(_ observer: Observer) -> Disposable where Observer.Element == Element {
if !CurrentThreadScheduler.isScheduleRequired {
let disposer = SinkDisposer()
let sinkAndSubscription = self.run(observer, cancel: disposer)
disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)
return disposer
} else {
return CurrentThreadScheduler.instance.schedule(()) { _ in
let disposer = SinkDisposer()
let sinkAndSubscription = self.run(observer, cancel: disposer)
disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)
return disposer
}
}
}
之前在学习RxSwift核心逻辑的时候,也经常路过这部分流程,这次我们看看这个分支到底是什么?CurrentThreadScheduler.isScheduleRequired
,当前线程调度者是否必需调用 schedule ?
public class CurrentThreadScheduler : ImmediateSchedulerType {
private static var isScheduleRequiredKey: pthread_key_t = { () -> pthread_key_t in
let key = UnsafeMutablePointer.allocate(capacity: 1)
defer { key.deallocate() }
guard pthread_key_create(key, nil) == 0 else {
rxFatalError("isScheduleRequired key creation failed")
}
return key.pointee
}()
static var queue : ScheduleQueue? {
get {
return Thread.getThreadLocalStorageValueForKey(CurrentThreadSchedulerQueueKey.instance)
}
set {
Thread.setThreadLocalStorageValue(newValue, forKey: CurrentThreadSchedulerQueueKey.instance)
}
}
/// Gets a value that indicates whether the caller must call a `schedule` method.
public static fileprivate(set) var isScheduleRequired: Bool {
get {
return pthread_getspecific(CurrentThreadScheduler.isScheduleRequiredKey) == nil
}
set(isScheduleRequired) {
if pthread_setspecific(CurrentThreadScheduler.isScheduleRequiredKey, isScheduleRequired ? nil : scheduleInProgressSentinel) != 0 {
rxFatalError("pthread_setspecific failed")
}
}
}
public func schedule(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable {
if CurrentThreadScheduler.isScheduleRequired {
CurrentThreadScheduler.isScheduleRequired = false
let disposable = action(state)
defer {
CurrentThreadScheduler.isScheduleRequired = true
CurrentThreadScheduler.queue = nil
}
guard let queue = CurrentThreadScheduler.queue else {
return disposable
}
while let latest = queue.value.dequeue() {
if latest.isDisposed {
continue
}
latest.invoke()
}
return disposable
}
let existingQueue = CurrentThreadScheduler.queue
let queue: RxMutableBox>
if let existingQueue = existingQueue {
queue = existingQueue
}
else {
queue = RxMutableBox(Queue(capacity: 1))
CurrentThreadScheduler.queue = queue
}
let scheduledItem = ScheduledItem(action: action, state: state)
queue.value.enqueue(scheduledItem)
return scheduledItem
}
}
CurrentThreadScheduler
调用isScheduleRequiredKey
的getter
时,用线程中存储的pthread_key_t
变量来标记是否需要调用 schedule 函数。pthread_key_t
变量的设置也是在isScheduleRequiredKey
的setter
中,后面在调用 schedule 函数后,第一步就是把isScheduleRequiredKey
设置为false
,pthread_key_t
也会被创建pthread_key_create
。
现在subscribe
中会走 else 部分,当前线程调用schedule
函数,传参一个元组和action闭包
。
schedule
函数中,第一个条件语句进来后,马上就置反了isScheduleRequiredKey
。然后就开始回调action闭包
。
中间序列ObserveOnSerialDispatchQueue
开始run
:
override func run(_ observer: Observer, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where Observer.Element == Element {
let sink = ObserveOnSerialDispatchQueueSink(scheduler: self.scheduler, observer: observer, cancel: cancel)
let subscription = self.source.subscribe(sink)
return (sink: sink, subscription: subscription)
}
ObserveOnSerialDispatchQueueSink
初始化时,除了保存串行队列调度者、匿名观察者、销毁者之外,还设置了一个匿名闭包:cachedScheduleLambda
。
init(scheduler: SerialDispatchQueueScheduler, observer: Observer, cancel: Cancelable) {
self.scheduler = scheduler
self.observer = observer
self.cancel = cancel
super.init()
self.cachedScheduleLambda = { pair in
guard !cancel.isDisposed else { return Disposables.create() }
pair.sink.observer.on(pair.event)
if pair.event.isStopEvent {
pair.sink.dispose()
}
return Disposables.create()
}
}
创建完中间序列管道ObserveOnSerialDispatchQueueSink
后,就是源序列开始订阅,把中间序列管道传入,最终作为源序列管道的观察者。此时,因为之前CurrentThreadScheduler.isScheduleRequired
已经是false
,所以走的是 Producer 的 subscribe 函数中第一个分支里面。然后源序列管道run
,开始响应订阅消息。
func run() -> Disposable {
return self._parent._scheduler.scheduleRecursive(self._parent._elements.makeIterator()) { iterator, recurse in
var mutableIterator = iterator
if let next = mutableIterator.next() {
self.forwardOn(.next(next))
recurse(mutableIterator)
} else {
self.forwardOn(.completed)
self.dispose()
}
}
}
这里面的代码确是让源序列的调度者(当前线程)去递归回调的。把源序列的元素迭代器(state)和响应信号的闭包传入。当前线程调度者是遵守ImmediateSchedulerType
协议的,我们在协议拓展中可以看到scheduleRecursive
的实现:
public func scheduleRecursive(_ state: State, action: @escaping (_ state: State, _ recurse: (State) -> Void) -> Void) -> Disposable {
let recursiveScheduler = RecursiveImmediateScheduler(action: action, scheduler: self)
recursiveScheduler.schedule(state)
return Disposables.create(with: recursiveScheduler.dispose)
}
重点是RecursiveImmediateScheduler
的schedule
:
func schedule(_ state: State) {
var scheduleState: ScheduleState = .initial
let d = self._scheduler.schedule(state) { state -> Disposable in
// best effort
if self._group.isDisposed {
return Disposables.create()
}
let action = self._lock.calculateLocked { () -> Action? in
switch scheduleState {
case let .added(removeKey):
self._group.remove(for: removeKey)
case .initial:
break
case .done:
break
}
scheduleState = .done
return self._action
}
if let action = action {
action(state, self.schedule)
}
return Disposables.create()
}
self._lock.performLocked {
switch scheduleState {
case .added:
rxFatalError("Invalid state")
case .initial:
if let removeKey = self._group.insert(d) {
scheduleState = .added(removeKey)
}
else {
scheduleState = .done
}
case .done:
break
}
}
}
看到这里真的懵了,之前不是就在CurrentThreadScheduler.instance.schedule
里面么?怎么又回到原点了?鬼撞墙?兜还在伊邪那美里面砍鼬。。。
从中间序列 subscribe 开始,到第一次判断是否必需执行 schedule 函数,条件语句中开始回调let disposable = action(state)
,这个action(state)
执行到源序列的调度者递归调用中又是self._scheduler.schedule
。
静心分析一下,只有第一次会走if
语句里面的,这次也是直接走了if
后面的。获取到当前线程的队列,把state
和action
包装成scheduledItem
,然后入队:queue.value.enqueue(scheduledItem)
。可以看到前面的if
里还有出队的代码:queue.value.dequeue()
,还没有执行到。这次调用 schedule 应该是为了管理队列。
代码走完,我们继续回到RecursiveImmediateScheduler
的schedule
下半部分,看起来像是对订阅生命周期的管理。
此时此刻才执行完了我们第一次CurrentThreadScheduler.instance.schedule
中action(state)
的回调。后面的主要就是scheduledItem
的调用了:latest.invoke()
:
func invoke() {
self._disposable.setDisposable(self._action(self._state))
}
然后才是之前那些闭包的回调:
latest.invoke()
self._disposable.setDisposable(self._action(self._state))
-
RecursiveImmediateScheduler
的schedule
里第二次调用 schedule:self._scheduler.schedule
的闭包 action(state, self.schedule)
- 源序列管道
run
中的闭包 self.forwardOn(.next(next))
self._observer.on(event)
前面我们记得源序列管道中的观察者是中间序列管道,那么就会到中间序列管道的onCore
里面。
override func onCore(_ event: Event) {
_ = self.scheduler.schedule((self, event), action: self.cachedScheduleLambda!)
}
又是它,又是 schedule 函数。不过这次的调用者是中间序列的串行调度者SerialDispatchQueueScheduler
:
func schedule(_ state: StateType, action: @escaping (StateType) -> Disposable) -> Disposable {
let cancel = SingleAssignmentDisposable()
self.queue.async {
if cancel.isDisposed {
return
}
cancel.setDisposable(action(state))
}
return cancel
}
很清楚了,self.queue.async
,用pthread_getspecific
找到这个线程的队列,然后异步执行。action 就是之前设置的匿名闭包:cachedScheduleLambda
:
self.cachedScheduleLambda = { pair in
guard !cancel.isDisposed else { return Disposables.create() }
pair.sink.observer.on(pair.event)
if pair.event.isStopEvent {
pair.sink.dispose()
}
return Disposables.create()
}
闭包里就是让中间序列管道的观察者去响应外界的订阅:pair.sink.observer.on(pair.event)
。
这样就完成了主线程中的序列发出的信号在子线程中响应外界的订阅。