0001    //
0002    //  VirtualTimeScheduler.swift
0003    //  Rx
0004    //
0005    //  Created by Krunoslav Zaher on 2/14/15.
0006    //  Copyright © 2015 Krunoslav Zaher. All rights reserved.
0007    //
0008    
0009    import Foundation
0010    
0011    /**
0012    Base class for virtual time schedulers using a priority queue for scheduled items.
0013    */
0014    public class VirtualTimeScheduler
HistoricalScheduler.swift:14
public class HistoricalScheduler : VirtualTimeScheduler<HistoricalSchedulerTimeConverter> {
VirtualTimeScheduler.swift:249
extension VirtualTimeScheduler {
<Converter
VirtualTimeScheduler.swift:18
    public typealias VirtualTime = Converter.VirtualTimeUnit
VirtualTimeScheduler.swift:19
    public typealias VirtualTimeInterval = Converter.VirtualTimeIntervalUnit
VirtualTimeScheduler.swift:26
    private var _converter: Converter
VirtualTimeScheduler.swift:49
    public init(initialClock: VirtualTime, converter: Converter) {
VirtualTimeScheduler.swift:117
    public func scheduleAbsoluteVirtual<StateType>(state: StateType, time: Converter.VirtualTimeUnit, action: StateType -> Disposable) -> Disposable {
VirtualTimeScheduler.swift:139
    public func adjustScheduledTime(time: Converter.VirtualTimeUnit) -> Converter.VirtualTimeUnit {
VirtualTimeScheduler.swift:139
    public func adjustScheduledTime(time: Converter.VirtualTimeUnit) -> Converter.VirtualTimeUnit {
: VirtualTimeConverterType> 0015 : SchedulerType 0016 , CustomDebugStringConvertible { 0017 0018 public typealias VirtualTime
VirtualTimeScheduler.swift:23
    private var _clock: VirtualTime
VirtualTimeScheduler.swift:25
    private var _schedulerQueue : PriorityQueue<VirtualSchedulerItem<VirtualTime>>
VirtualTimeScheduler.swift:40
    public var clock: VirtualTime {
VirtualTimeScheduler.swift:49
    public init(initialClock: VirtualTime, converter: Converter) {
VirtualTimeScheduler.swift:170
    func findNext() -> VirtualSchedulerItem<VirtualTime>? {
VirtualTimeScheduler.swift:188
    public func advanceTo(virtualTime: VirtualTime) {
= Converter.VirtualTimeUnit 0019 public typealias VirtualTimeInterval
VirtualTimeScheduler.swift:104
    public func scheduleRelativeVirtual<StateType>(state: StateType, dueTime: VirtualTimeInterval, action: StateType -> Disposable) -> Disposable {
VirtualTimeScheduler.swift:220
    public func sleep(virtualInterval: VirtualTimeInterval) {
= Converter.VirtualTimeIntervalUnit 0020 0021 private var _running
VirtualTimeScheduler.swift:51
        _running = false
VirtualTimeScheduler.swift:149
        if _running {
VirtualTimeScheduler.swift:153
        _running = true
VirtualTimeScheduler.swift:165
        } while _running
VirtualTimeScheduler.swift:167
        _running = false
VirtualTimeScheduler.swift:191
        if _running {
VirtualTimeScheduler.swift:195
        _running = true
VirtualTimeScheduler.swift:211
        } while _running
VirtualTimeScheduler.swift:214
        _running = false
VirtualTimeScheduler.swift:237
        _running = false
: Bool 0022 0023 private var _clock
VirtualTimeScheduler.swift:41
        return _clock
VirtualTimeScheduler.swift:50
        _clock = initialClock
VirtualTimeScheduler.swift:160
                _clock = next.time
VirtualTimeScheduler.swift:206
                _clock = next.time
VirtualTimeScheduler.swift:213
        _clock = virtualTime
VirtualTimeScheduler.swift:228
        _clock = sleepTo
: VirtualTime 0024 0025 private var _schedulerQueue
VirtualTimeScheduler.swift:53
        _schedulerQueue = PriorityQueue(hasHigherPriority: {
VirtualTimeScheduler.swift:129
        _schedulerQueue.enqueue(item)
VirtualTimeScheduler.swift:164
            _schedulerQueue.remove(next)
VirtualTimeScheduler.swift:171
        while let front = _schedulerQueue.peek() {
VirtualTimeScheduler.swift:173
                _schedulerQueue.remove(front)
VirtualTimeScheduler.swift:210
            _schedulerQueue.remove(next)
VirtualTimeScheduler.swift:255
            return self._schedulerQueue.debugDescription
: PriorityQueue<VirtualSchedulerItem<VirtualTime>> 0026 private var _converter
VirtualTimeScheduler.swift:34
        return _converter.convertFromVirtualTime(clock)
VirtualTimeScheduler.swift:52
        _converter = converter
VirtualTimeScheduler.swift:91
        let absoluteTime = _converter.convertToVirtualTime(time)
VirtualTimeScheduler.swift:105
        let time = _converter.offsetVirtualTime(time: self.clock, offset: dueTime)
VirtualTimeScheduler.swift:159
            if _converter.compareVirtualTime(next.time, self.clock).greaterThan  {
VirtualTimeScheduler.swift:201
            if _converter.compareVirtualTime(next.time, virtualTime).greaterThan {
VirtualTimeScheduler.swift:205
            if _converter.compareVirtualTime(next.time, self.clock).greaterThan  {
VirtualTimeScheduler.swift:223
        let sleepTo = _converter.offsetVirtualTime(time: clock, offset: virtualInterval)
VirtualTimeScheduler.swift:224
        if _converter.compareVirtualTime(sleepTo, clock).lessThen {
: Converter 0027 0028 private var _nextId
VirtualTimeScheduler.swift:125
        }, time: time, id: _nextId)
VirtualTimeScheduler.swift:127
        _nextId += 1
= 0 0029 0030 /** 0031 - returns: Current time. 0032 */ 0033 public var now
VirtualTimeScheduler.swift:90
        let time = self.now.dateByAddingTimeInterval(dueTime)
: RxTime { 0034 return _converter.convertFromVirtualTime(clock) 0035 } 0036 0037 /** 0038 - returns: Scheduler's absolute time clock value. 0039 */ 0040 public var clock
VirtualTimeScheduler.swift:34
        return _converter.convertFromVirtualTime(clock)
VirtualTimeScheduler.swift:105
        let time = _converter.offsetVirtualTime(time: self.clock, offset: dueTime)
VirtualTimeScheduler.swift:159
            if _converter.compareVirtualTime(next.time, self.clock).greaterThan  {
VirtualTimeScheduler.swift:205
            if _converter.compareVirtualTime(next.time, self.clock).greaterThan  {
VirtualTimeScheduler.swift:223
        let sleepTo = _converter.offsetVirtualTime(time: clock, offset: virtualInterval)
VirtualTimeScheduler.swift:224
        if _converter.compareVirtualTime(sleepTo, clock).lessThen {
: VirtualTime { 0041 return _clock 0042 } 0043 0044 /** 0045 Creates a new virtual time scheduler. 0046 0047 - parameter initialClock: Initial value for the clock. 0048 */ 0049 public init
HistoricalScheduler.swift:22
        super.init(initialClock: initialClock, converter: HistoricalSchedulerTimeConverter())
(initialClock: VirtualTime, converter: Converter) { 0050 _clock = initialClock 0051 _running = false 0052 _converter = converter 0053 _schedulerQueue = PriorityQueue(hasHigherPriority: { 0054 switch converter.compareVirtualTime($0.time, $1.time) { 0055 case .LessThan: 0056 return true 0057 case .Equal: 0058 return $0.id < $1.id 0059 case .GreaterThan: 0060 return false 0061 } 0062 }) 0063 #if TRACE_RESOURCES 0064 AtomicIncrement(&resourceCount) 0065 #endif 0066 } 0067 0068 /** 0069 Schedules an action to be executed immediatelly. 0070 0071 - parameter state: State passed to the action to be executed. 0072 - parameter action: Action to be executed. 0073 - returns: The disposable object used to cancel the scheduled action (best effort). 0074 */ 0075 public func schedule<StateType>(state: StateType, action: StateType -> Disposable) -> Disposable { 0076 return self.scheduleRelative(state, dueTime: 0.0) { a in 0077 return action(a) 0078 } 0079 } 0080 0081 /** 0082 Schedules an action to be executed. 0083 0084 - parameter state: State passed to the action to be executed. 0085 - parameter dueTime: Relative time after which to execute the action. 0086 - parameter action: Action to be executed. 0087 - returns: The disposable object used to cancel the scheduled action (best effort). 0088 */ 0089 public func scheduleRelative
VirtualTimeScheduler.swift:76
        return self.scheduleRelative(state, dueTime: 0.0) { a in
<StateType>(state: StateType, dueTime: RxTimeInterval, action: StateType -> Disposable) -> Disposable { 0090 let time = self.now.dateByAddingTimeInterval(dueTime) 0091 let absoluteTime = _converter.convertToVirtualTime(time) 0092 let adjustedTime = self.adjustScheduledTime(absoluteTime) 0093 return scheduleAbsoluteVirtual(state, time: adjustedTime, action: action) 0094 } 0095 0096 /** 0097 Schedules an action to be executed after relative time has passed. 0098 0099 - parameter state: State passed to the action to be executed. 0100 - parameter time: Absolute time when to execute the action. If this is less or equal then `now`, `now + 1` will be used. 0101 - parameter action: Action to be executed. 0102 - returns: The disposable object used to cancel the scheduled action (best effort). 0103 */ 0104 public func scheduleRelativeVirtual<StateType>(state: StateType, dueTime: VirtualTimeInterval, action: StateType -> Disposable) -> Disposable { 0105 let time = _converter.offsetVirtualTime(time: self.clock, offset: dueTime) 0106 return scheduleAbsoluteVirtual(state, time: time, action: action) 0107 } 0108 0109 /** 0110 Schedules an action to be executed at absolute virtual time. 0111 0112 - parameter state: State passed to the action to be executed. 0113 - parameter time: Absolute time when to execute the action. 0114 - parameter action: Action to be executed. 0115 - returns: The disposable object used to cancel the scheduled action (best effort). 0116 */ 0117 public func scheduleAbsoluteVirtual
VirtualTimeScheduler.swift:93
        return scheduleAbsoluteVirtual(state, time: adjustedTime, action: action)
VirtualTimeScheduler.swift:106
        return scheduleAbsoluteVirtual(state, time: time, action: action)
<StateType>(state: StateType, time: Converter.VirtualTimeUnit, action: StateType -> Disposable) -> Disposable { 0118 MainScheduler.ensureExecutingOnScheduler() 0119 0120 let compositeDisposable = CompositeDisposable() 0121 0122 let item = VirtualSchedulerItem(action: { 0123 let dispose = action(state) 0124 return dispose 0125 }, time: time, id: _nextId) 0126 0127 _nextId += 1 0128 0129 _schedulerQueue.enqueue(item) 0130 0131 compositeDisposable.addDisposable(item) 0132 0133 return compositeDisposable 0134 } 0135 0136 /** 0137 Adjusts time of scheduling before adding item to schedule queue. 0138 */ 0139 public func adjustScheduledTime
VirtualTimeScheduler.swift:92
        let adjustedTime = self.adjustScheduledTime(absoluteTime)
(time: Converter.VirtualTimeUnit) -> Converter.VirtualTimeUnit { 0140 return time 0141 } 0142 0143 /** 0144 Starts the virtual time scheduler. 0145 */ 0146 public func start() { 0147 MainScheduler.ensureExecutingOnScheduler() 0148 0149 if _running { 0150 return 0151 } 0152 0153 _running = true 0154 repeat { 0155 guard let next = findNext() else { 0156 break 0157 } 0158 0159 if _converter.compareVirtualTime(next.time, self.clock).greaterThan { 0160 _clock = next.time 0161 } 0162 0163 next.invoke() 0164 _schedulerQueue.remove(next) 0165 } while _running 0166 0167 _running = false 0168 } 0169 0170 func findNext
VirtualTimeScheduler.swift:155
            guard let next = findNext() else {
VirtualTimeScheduler.swift:197
            guard let next = findNext() else {
() -> VirtualSchedulerItem<VirtualTime>? { 0171 while let front = _schedulerQueue.peek() { 0172 if front.disposed { 0173 _schedulerQueue.remove(front) 0174 continue 0175 } 0176 0177 return front 0178 } 0179 0180 return nil 0181 } 0182 0183 /** 0184 Advances the scheduler's clock to the specified time, running all work till that point. 0185 0186 - parameter virtualTime: Absolute time to advance the scheduler's clock to. 0187 */ 0188 public func advanceTo(virtualTime: VirtualTime) { 0189 MainScheduler.ensureExecutingOnScheduler() 0190 0191 if _running { 0192 fatalError("Scheduler is already running") 0193 } 0194 0195 _running = true 0196 repeat { 0197 guard let next = findNext() else { 0198 break 0199 } 0200 0201 if _converter.compareVirtualTime(next.time, virtualTime).greaterThan { 0202 break 0203 } 0204 0205 if _converter.compareVirtualTime(next.time, self.clock).greaterThan { 0206 _clock = next.time 0207 } 0208 0209 next.invoke() 0210 _schedulerQueue.remove(next) 0211 } while _running 0212 0213 _clock = virtualTime 0214 _running = false 0215 } 0216 0217 /** 0218 Advances the scheduler's clock by the specified relative time. 0219 */ 0220 public func sleep(virtualInterval: VirtualTimeInterval) { 0221 MainScheduler.ensureExecutingOnScheduler() 0222 0223 let sleepTo = _converter.offsetVirtualTime(time: clock, offset: virtualInterval) 0224 if _converter.compareVirtualTime(sleepTo, clock).lessThen { 0225 fatalError("Can't sleep to past.") 0226 } 0227 0228 _clock = sleepTo 0229 } 0230 0231 /** 0232 Stops the virtual time scheduler. 0233 */ 0234 public func stop() { 0235 MainScheduler.ensureExecutingOnScheduler() 0236 0237 _running = false 0238 } 0239 0240 #if TRACE_RESOURCES 0241 deinit { 0242 AtomicDecrement(&resourceCount) 0243 } 0244 #endif 0245 } 0246 0247 // MARK: description 0248 0249 extension VirtualTimeScheduler { 0250 /** 0251 A textual representation of `self`, suitable for debugging. 0252 */ 0253 public var debugDescription: String { 0254 get { 0255 return self._schedulerQueue.debugDescription 0256 } 0257 } 0258 } 0259 0260 class VirtualSchedulerItem
VirtualTimeScheduler.swift:25
    private var _schedulerQueue : PriorityQueue<VirtualSchedulerItem<VirtualTime>>
VirtualTimeScheduler.swift:122
        let item = VirtualSchedulerItem(action: {
VirtualTimeScheduler.swift:170
    func findNext() -> VirtualSchedulerItem<VirtualTime>? {
VirtualTimeScheduler.swift:291
extension VirtualSchedulerItem
<Time
VirtualTimeScheduler.swift:265
    let time: Time
VirtualTimeScheduler.swift:276
    init(action: Action, time: Time, id: Int) {
> 0261 : Disposable { 0262 typealias Action
VirtualTimeScheduler.swift:264
    let action: Action
VirtualTimeScheduler.swift:276
    init(action: Action, time: Time, id: Int) {
= () -> Disposable 0263 0264 let action
VirtualTimeScheduler.swift:277
        self.action = action
VirtualTimeScheduler.swift:283
         self.disposable.disposable = action()
: Action 0265 let time
VirtualTimeScheduler.swift:54
            switch converter.compareVirtualTime($0.time, $1.time) {
VirtualTimeScheduler.swift:54
            switch converter.compareVirtualTime($0.time, $1.time) {
VirtualTimeScheduler.swift:159
            if _converter.compareVirtualTime(next.time, self.clock).greaterThan  {
VirtualTimeScheduler.swift:160
                _clock = next.time
VirtualTimeScheduler.swift:201
            if _converter.compareVirtualTime(next.time, virtualTime).greaterThan {
VirtualTimeScheduler.swift:205
            if _converter.compareVirtualTime(next.time, self.clock).greaterThan  {
VirtualTimeScheduler.swift:206
                _clock = next.time
VirtualTimeScheduler.swift:278
        self.time = time
VirtualTimeScheduler.swift:294
        return "\(time)"
: Time 0266 let id
VirtualTimeScheduler.swift:58
                return $0.id < $1.id
VirtualTimeScheduler.swift:58
                return $0.id < $1.id
VirtualTimeScheduler.swift:279
        self.id = id
: Int 0267 0268 var disposed
VirtualTimeScheduler.swift:172
            if front.disposed {
: Bool { 0269 get { 0270 return disposable.disposed 0271 } 0272 } 0273 0274 var disposable
VirtualTimeScheduler.swift:270
            return disposable.disposed
VirtualTimeScheduler.swift:283
         self.disposable.disposable = action()
VirtualTimeScheduler.swift:287
        self.disposable.dispose()
= SingleAssignmentDisposable() 0275 0276 init
VirtualTimeScheduler.swift:122
        let item = VirtualSchedulerItem(action: {
(action: Action, time: Time, id: Int) { 0277 self.action = action 0278 self.time = time 0279 self.id = id 0280 } 0281 0282 func invoke
VirtualTimeScheduler.swift:163
            next.invoke()
VirtualTimeScheduler.swift:209
            next.invoke()
() { 0283 self.disposable.disposable = action() 0284 } 0285 0286 func dispose() { 0287 self.disposable.dispose() 0288 } 0289 } 0290 0291 extension VirtualSchedulerItem 0292 : CustomDebugStringConvertible { 0293 var debugDescription: String { 0294 return "\(time)" 0295 } 0296 }