From 16ca28f31c300f92a8225b4901a40366f70662ea Mon Sep 17 00:00:00 2001 From: Daniel Tartaglia Date: Wed, 10 Jul 2024 13:25:54 -0400 Subject: [PATCH 1/2] Allow VirtualTimeScheduler to run on any thread as long as critical methods are all called on the same thread. --- RxSwift/Schedulers/VirtualTimeScheduler.swift | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/RxSwift/Schedulers/VirtualTimeScheduler.swift b/RxSwift/Schedulers/VirtualTimeScheduler.swift index 4f55d29d7..b54b6144c 100644 --- a/RxSwift/Schedulers/VirtualTimeScheduler.swift +++ b/RxSwift/Schedulers/VirtualTimeScheduler.swift @@ -24,6 +24,8 @@ open class VirtualTimeScheduler private var nextId = 0 + private var thread: Thread! + /// - returns: Current time. public var now: RxTime { self.converter.convertFromVirtualTime(self.clock) @@ -106,7 +108,10 @@ open class VirtualTimeScheduler - returns: The disposable object used to cancel the scheduled action (best effort). */ public func scheduleAbsoluteVirtual(_ state: StateType, time: VirtualTime, action: @escaping (StateType) -> Disposable) -> Disposable { - MainScheduler.ensureExecutingOnScheduler() + guard thread == nil || Thread.current == thread else { + rxFatalError("Executing on the wrong thread. Please ensure all work on the same thread.") + } + thread = Thread.current let compositeDisposable = CompositeDisposable() @@ -130,12 +135,15 @@ open class VirtualTimeScheduler /// Starts the virtual time scheduler. public func start() { - MainScheduler.ensureExecutingOnScheduler() - if self.running { return } + guard thread == nil || Thread.current == thread else { + rxFatalError("Executing on the wrong thread. Please ensure all work on the same thread.") + } + thread = Thread.current + self.running = true repeat { guard let next = self.findNext() else { @@ -170,12 +178,15 @@ open class VirtualTimeScheduler /// /// - parameter virtualTime: Absolute time to advance the scheduler's clock to. public func advanceTo(_ virtualTime: VirtualTime) { - MainScheduler.ensureExecutingOnScheduler() - if self.running { fatalError("Scheduler is already running") } + guard thread == nil || Thread.current == thread else { + rxFatalError("Executing on the wrong thread. Please ensure all work on the same thread.") + } + thread = Thread.current + self.running = true repeat { guard let next = self.findNext() else { @@ -199,7 +210,10 @@ open class VirtualTimeScheduler /// Advances the scheduler's clock by the specified relative time. public func sleep(_ virtualInterval: VirtualTimeInterval) { - MainScheduler.ensureExecutingOnScheduler() + guard thread == nil || Thread.current == thread else { + rxFatalError("Executing on the wrong thread. Please ensure all work on the same thread.") + } + thread = Thread.current let sleepTo = self.converter.offsetVirtualTime(self.clock, offset: virtualInterval) if self.converter.compareVirtualTime(sleepTo, self.clock).lessThen { @@ -211,7 +225,10 @@ open class VirtualTimeScheduler /// Stops the virtual time scheduler. public func stop() { - MainScheduler.ensureExecutingOnScheduler() + guard thread == nil || Thread.current == thread else { + rxFatalError("Executing on the wrong thread. Please ensure all work on the same thread.") + } + thread = Thread.current self.running = false } From f63eb1361492955380e3c93862fe26449daa9182 Mon Sep 17 00:00:00 2001 From: Daniel Tartaglia Date: Wed, 17 Jul 2024 11:17:02 -0400 Subject: [PATCH 2/2] Move thread assignment to init method. --- RxSwift/Schedulers/VirtualTimeScheduler.swift | 39 +++++++------------ 1 file changed, 13 insertions(+), 26 deletions(-) diff --git a/RxSwift/Schedulers/VirtualTimeScheduler.swift b/RxSwift/Schedulers/VirtualTimeScheduler.swift index b54b6144c..5d2d61e14 100644 --- a/RxSwift/Schedulers/VirtualTimeScheduler.swift +++ b/RxSwift/Schedulers/VirtualTimeScheduler.swift @@ -24,7 +24,7 @@ open class VirtualTimeScheduler private var nextId = 0 - private var thread: Thread! + private let thread: Thread /// - returns: Current time. public var now: RxTime { @@ -43,6 +43,7 @@ open class VirtualTimeScheduler self.currentClock = initialClock self.running = false self.converter = converter + self.thread = Thread.current self.schedulerQueue = PriorityQueue(hasHigherPriority: { switch converter.compareVirtualTime($0.time, $1.time) { case .lessThan: @@ -108,11 +109,7 @@ open class VirtualTimeScheduler - returns: The disposable object used to cancel the scheduled action (best effort). */ public func scheduleAbsoluteVirtual(_ state: StateType, time: VirtualTime, action: @escaping (StateType) -> Disposable) -> Disposable { - guard thread == nil || Thread.current == thread else { - rxFatalError("Executing on the wrong thread. Please ensure all work on the same thread.") - } - thread = Thread.current - + ensusreRunningOnCorrectThread() let compositeDisposable = CompositeDisposable() let item = VirtualSchedulerItem(action: { @@ -139,11 +136,7 @@ open class VirtualTimeScheduler return } - guard thread == nil || Thread.current == thread else { - rxFatalError("Executing on the wrong thread. Please ensure all work on the same thread.") - } - thread = Thread.current - + ensusreRunningOnCorrectThread() self.running = true repeat { guard let next = self.findNext() else { @@ -182,11 +175,7 @@ open class VirtualTimeScheduler fatalError("Scheduler is already running") } - guard thread == nil || Thread.current == thread else { - rxFatalError("Executing on the wrong thread. Please ensure all work on the same thread.") - } - thread = Thread.current - + ensusreRunningOnCorrectThread() self.running = true repeat { guard let next = self.findNext() else { @@ -210,11 +199,7 @@ open class VirtualTimeScheduler /// Advances the scheduler's clock by the specified relative time. public func sleep(_ virtualInterval: VirtualTimeInterval) { - guard thread == nil || Thread.current == thread else { - rxFatalError("Executing on the wrong thread. Please ensure all work on the same thread.") - } - thread = Thread.current - + ensusreRunningOnCorrectThread() let sleepTo = self.converter.offsetVirtualTime(self.clock, offset: virtualInterval) if self.converter.compareVirtualTime(sleepTo, self.clock).lessThen { fatalError("Can't sleep to past.") @@ -225,11 +210,7 @@ open class VirtualTimeScheduler /// Stops the virtual time scheduler. public func stop() { - guard thread == nil || Thread.current == thread else { - rxFatalError("Executing on the wrong thread. Please ensure all work on the same thread.") - } - thread = Thread.current - + ensusreRunningOnCorrectThread() self.running = false } @@ -238,6 +219,12 @@ open class VirtualTimeScheduler _ = Resources.decrementTotal() } #endif + + private func ensusreRunningOnCorrectThread() { + guard Thread.current == thread else { + rxFatalError("Executing on the wrong thread. Please ensure all work on the same thread.") + } + } } // MARK: description