RxSwift之scheduler

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()
}
  1. 创建Producer的子类ObservableSequence
  2. ObservableSequence两个属性:
    1. _elements: Sequence(N个元素)
    2. _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调用isScheduleRequiredKeygetter时,用线程中存储的pthread_key_t变量来标记是否需要调用 schedule 函数。pthread_key_t变量的设置也是在isScheduleRequiredKeysetter中,后面在调用 schedule 函数后,第一步就是把isScheduleRequiredKey设置为falsepthread_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)
}

重点是RecursiveImmediateSchedulerschedule

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后面的。获取到当前线程的队列,把stateaction包装成scheduledItem,然后入队:queue.value.enqueue(scheduledItem)。可以看到前面的if里还有出队的代码:queue.value.dequeue(),还没有执行到。这次调用 schedule 应该是为了管理队列。

代码走完,我们继续回到RecursiveImmediateSchedulerschedule下半部分,看起来像是对订阅生命周期的管理。

此时此刻才执行完了我们第一次CurrentThreadScheduler.instance.scheduleaction(state)的回调。后面的主要就是scheduledItem的调用了:latest.invoke()

func invoke() {
    self._disposable.setDisposable(self._action(self._state))
}

然后才是之前那些闭包的回调:

  • latest.invoke()
  • self._disposable.setDisposable(self._action(self._state))
  • RecursiveImmediateSchedulerschedule里第二次调用 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)

这样就完成了主线程中的序列发出的信号在子线程中响应外界的订阅。

你可能感兴趣的:(RxSwift之scheduler)