From fdf579786d16b78d0ea8e0267e24861f5f346d76 Mon Sep 17 00:00:00 2001 From: "John C. Daub" Date: Wed, 30 Dec 2015 08:08:57 -0600 Subject: [PATCH 1/5] Adding `DispatchQueueSchedulerQOS` enum, which provides the Apple-recommended quality of service classes. --- Rx.xcodeproj/project.pbxproj | 10 +++++ .../DispatchQueueSchedulerQOS.swift | 40 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 RxSwift/Schedulers/DispatchQueueSchedulerQOS.swift diff --git a/Rx.xcodeproj/project.pbxproj b/Rx.xcodeproj/project.pbxproj index 4d8400a8..7be24a2a 100644 --- a/Rx.xcodeproj/project.pbxproj +++ b/Rx.xcodeproj/project.pbxproj @@ -7,6 +7,10 @@ objects = { /* Begin PBXBuildFile section */ + 79E9DE891C3417FD009970AF /* DispatchQueueSchedulerQOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79E9DE881C3417FD009970AF /* DispatchQueueSchedulerQOS.swift */; }; + 79E9DE8A1C3417FD009970AF /* DispatchQueueSchedulerQOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79E9DE881C3417FD009970AF /* DispatchQueueSchedulerQOS.swift */; }; + 79E9DE8B1C3417FD009970AF /* DispatchQueueSchedulerQOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79E9DE881C3417FD009970AF /* DispatchQueueSchedulerQOS.swift */; }; + 79E9DE8C1C3417FD009970AF /* DispatchQueueSchedulerQOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79E9DE881C3417FD009970AF /* DispatchQueueSchedulerQOS.swift */; }; 9BA1CBD31C0F7D550044B50A /* UIActivityIndicatorView+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BA1CBD11C0F7C0A0044B50A /* UIActivityIndicatorView+Rx.swift */; }; 9BA1CBFD1C0F84A10044B50A /* UIActivityIndicatorView+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BA1CBD11C0F7C0A0044B50A /* UIActivityIndicatorView+Rx.swift */; }; 9BA1CBFE1C0F84C40044B50A /* UIActivityIndicatorView+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BA1CBD11C0F7C0A0044B50A /* UIActivityIndicatorView+Rx.swift */; }; @@ -1004,6 +1008,7 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 79E9DE881C3417FD009970AF /* DispatchQueueSchedulerQOS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DispatchQueueSchedulerQOS.swift; sourceTree = ""; }; 9BA1CBD11C0F7C0A0044B50A /* UIActivityIndicatorView+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIActivityIndicatorView+Rx.swift"; sourceTree = ""; }; A111CE961B91C97C00D0DCEE /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; B1B7C3BC1BDD39DB0076934E /* TakeLast.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TakeLast.swift; sourceTree = ""; }; @@ -1572,6 +1577,7 @@ C8B144FA1BD2D44500267DCE /* ConcurrentMainScheduler.swift */, C8C3DA0E1B939767004D233E /* CurrentThreadScheduler.swift */, C8093CB61B8A72BE0088E94D /* DispatchQueueSchedulerPriority.swift */, + 79E9DE881C3417FD009970AF /* DispatchQueueSchedulerQOS.swift */, C8B144FF1BD2D80100267DCE /* ImmediateScheduler.swift */, C8093CB71B8A72BE0088E94D /* MainScheduler.swift */, C8093CB81B8A72BE0088E94D /* OperationQueueScheduler.swift */, @@ -2770,6 +2776,7 @@ C84CC5591BDCF51200E06A64 /* SynchronizedSubscribeType.swift in Sources */, C8093D321B8A72BE0088E94D /* Reduce.swift in Sources */, C8640A041BA5B12A00D3C4E8 /* Repeat.swift in Sources */, + 79E9DE8A1C3417FD009970AF /* DispatchQueueSchedulerQOS.swift in Sources */, C8093CF41B8A72BE0088E94D /* Errors.swift in Sources */, C8093D141B8A72BE0088E94D /* Debug.swift in Sources */, CB883B4B1BE369AA000AC2EE /* AddRef.swift in Sources */, @@ -2994,6 +3001,7 @@ C84CC5581BDCF51200E06A64 /* SynchronizedSubscribeType.swift in Sources */, C8093D311B8A72BE0088E94D /* Reduce.swift in Sources */, C8640A031BA5B12A00D3C4E8 /* Repeat.swift in Sources */, + 79E9DE891C3417FD009970AF /* DispatchQueueSchedulerQOS.swift in Sources */, C8093CF31B8A72BE0088E94D /* Errors.swift in Sources */, C8093D131B8A72BE0088E94D /* Debug.swift in Sources */, CB883B4A1BE369AA000AC2EE /* AddRef.swift in Sources */, @@ -3142,6 +3150,7 @@ C84CC55B1BDCF51200E06A64 /* SynchronizedSubscribeType.swift in Sources */, C8F0BFE51BBBFB8B001B112F /* Reduce.swift in Sources */, C8F0BFE71BBBFB8B001B112F /* Repeat.swift in Sources */, + 79E9DE8C1C3417FD009970AF /* DispatchQueueSchedulerQOS.swift in Sources */, C8F0BFE81BBBFB8B001B112F /* Errors.swift in Sources */, C8F0BFE91BBBFB8B001B112F /* Debug.swift in Sources */, CB883B4D1BE369AA000AC2EE /* AddRef.swift in Sources */, @@ -3459,6 +3468,7 @@ C84CC55A1BDCF51200E06A64 /* SynchronizedSubscribeType.swift in Sources */, D2EBEB3B1BB9B6D8003A27DC /* OperationQueueScheduler.swift in Sources */, D2EBEAE51BB9B697003A27DC /* AnyObserver.swift in Sources */, + 79E9DE8B1C3417FD009970AF /* DispatchQueueSchedulerQOS.swift in Sources */, D2EBEB3D1BB9B6D8003A27DC /* SchedulerServices+Emulation.swift in Sources */, D2EBEB1C1BB9B6C1003A27DC /* Sample.swift in Sources */, D2EBEAFD1BB9B6BA003A27DC /* AnonymousObservable.swift in Sources */, diff --git a/RxSwift/Schedulers/DispatchQueueSchedulerQOS.swift b/RxSwift/Schedulers/DispatchQueueSchedulerQOS.swift new file mode 100644 index 00000000..e9224acf --- /dev/null +++ b/RxSwift/Schedulers/DispatchQueueSchedulerQOS.swift @@ -0,0 +1,40 @@ +// +// DispatchQueueSchedulerQOS.swift +// RxSwift +// +// Created by John C. "Hsoi" Daub on 12/30/15. +// Copyright © 2015 Krunoslav Zaher. All rights reserved. +// + +import Foundation + +/** +Identifies one of the global concurrent dispatch queues with specified quality of service class. +*/ +public enum DispatchQueueSchedulerQOS { + + /** + Identifies global dispatch queue with `QOS_CLASS_USER_INTERACTIVE` + */ + case UserInteractive + + /** + Identifies global dispatch queue with `QOS_CLASS_USER_INITIATED` + */ + case UserInitiated + + /** + Identifies global dispatch queue with `QOS_CLASS_DEFAULT` + */ + case Default + + /** + Identifies global dispatch queue with `QOS_CLASS_UTILITY` + */ + case Utility + + /** + Identifies global dispatch queue with `QOS_CLASS_BACKGROUND` + */ + case Background +} From f57230f9efce6967d7c9d7d8227009f1e1627ce0 Mon Sep 17 00:00:00 2001 From: "John C. Daub" Date: Wed, 30 Dec 2015 08:09:50 -0600 Subject: [PATCH 2/5] Update ConcurrentDispatchQueueScheduler and SerialDispatchQueueScheudler to adopt the new QOS enums. Add deprecation warnings to the priority mechanisms. --- .../ConcurrentDispatchQueueScheduler.swift | 24 +++++++++++++++++ .../DispatchQueueSchedulerPriority.swift | 1 + .../SerialDispatchQueueScheduler.swift | 26 ++++++++++++++++++- 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/RxSwift/Schedulers/ConcurrentDispatchQueueScheduler.swift b/RxSwift/Schedulers/ConcurrentDispatchQueueScheduler.swift index 7efb71c2..6e65224a 100644 --- a/RxSwift/Schedulers/ConcurrentDispatchQueueScheduler.swift +++ b/RxSwift/Schedulers/ConcurrentDispatchQueueScheduler.swift @@ -42,6 +42,7 @@ public class ConcurrentDispatchQueueScheduler: SchedulerType { - parameter globalConcurrentQueuePriority: Target global dispatch queue. */ + @available(*, deprecated=2.0.0, message="Use init(globalConcurrentQueueQOS:) instead.") public convenience init(globalConcurrentQueuePriority: DispatchQueueSchedulerPriority) { var priority: Int = 0 switch globalConcurrentQueuePriority { @@ -55,6 +56,29 @@ public class ConcurrentDispatchQueueScheduler: SchedulerType { self.init(queue: dispatch_get_global_queue(priority, UInt(0))) } + /** + Convenience init for scheduler that wraps one of the global concurrent dispatch queues. + + - parameter globalConcurrentQueueQOS: Target global dispatch queue, by quality of service class. + */ + public convenience init(globalConcurrentQueueQOS: DispatchQueueSchedulerQOS) { + let priority: qos_class_t + switch globalConcurrentQueueQOS { + case .UserInteractive: + priority = QOS_CLASS_USER_INTERACTIVE + case .UserInitiated: + priority = QOS_CLASS_USER_INITIATED + case .Default: + priority = QOS_CLASS_DEFAULT + case .Utility: + priority = QOS_CLASS_UTILITY + case .Background: + priority = QOS_CLASS_BACKGROUND + } + self.init(queue: dispatch_get_global_queue(priority, UInt(0))) + } + + class func convertTimeIntervalToDispatchInterval(timeInterval: NSTimeInterval) -> Int64 { return Int64(timeInterval * Double(NSEC_PER_SEC)) } diff --git a/RxSwift/Schedulers/DispatchQueueSchedulerPriority.swift b/RxSwift/Schedulers/DispatchQueueSchedulerPriority.swift index 63d4a14f..80ecada1 100644 --- a/RxSwift/Schedulers/DispatchQueueSchedulerPriority.swift +++ b/RxSwift/Schedulers/DispatchQueueSchedulerPriority.swift @@ -11,6 +11,7 @@ import Foundation /** Identifies one of the global concurrent dispatch queues with specified priority. */ +@available(*, deprecated=2.0.0, message="Use DispatchQueueSchedulerQOS instead.") public enum DispatchQueueSchedulerPriority { /** diff --git a/RxSwift/Schedulers/SerialDispatchQueueScheduler.swift b/RxSwift/Schedulers/SerialDispatchQueueScheduler.swift index c50014ae..10c9dd00 100644 --- a/RxSwift/Schedulers/SerialDispatchQueueScheduler.swift +++ b/RxSwift/Schedulers/SerialDispatchQueueScheduler.swift @@ -79,6 +79,7 @@ public class SerialDispatchQueueScheduler: SchedulerType { - parameter globalConcurrentQueuePriority: Identifier for global dispatch queue with specified priority. - parameter internalSerialQueueName: Custom name for internal serial dispatch queue proxy. */ + @available(*, deprecated=2.0.0, message="Use init(globalConcurrentQueueQOS:,internalSerialQueueName:) instead.") public convenience init(globalConcurrentQueuePriority: DispatchQueueSchedulerPriority, internalSerialQueueName: String = "rx.global_dispatch_queue.serial") { var priority: Int = 0 switch globalConcurrentQueuePriority { @@ -91,7 +92,30 @@ public class SerialDispatchQueueScheduler: SchedulerType { } self.init(queue: dispatch_get_global_queue(priority, UInt(0)), internalSerialQueueName: internalSerialQueueName) } - + + /** + Constructs new `SerialDispatchQueueScheduler` that wraps on of the global concurrent dispatch queues. + + - parameter globalConcurrentQueueQOS: Identifier for global dispatch queue with specified quality of service class. + - parameter internalSerialQueueName: Custom name for internal serial dispatch queue proxy. + */ + public convenience init(globalConcurrentQueueQOS: DispatchQueueSchedulerQOS, internalSerialQueueName: String = "rx.global_dispatch_queue.serial") { + let priority: qos_class_t + switch globalConcurrentQueueQOS { + case .UserInteractive: + priority = QOS_CLASS_USER_INTERACTIVE + case .UserInitiated: + priority = QOS_CLASS_USER_INITIATED + case .Default: + priority = QOS_CLASS_DEFAULT + case .Utility: + priority = QOS_CLASS_UTILITY + case .Background: + priority = QOS_CLASS_BACKGROUND + } + self.init(queue: dispatch_get_global_queue(priority, UInt(0)), internalSerialQueueName: internalSerialQueueName) + } + class func convertTimeIntervalToDispatchInterval(timeInterval: NSTimeInterval) -> Int64 { return Int64(timeInterval * Double(NSEC_PER_SEC)) } From b3f4bf13f2d31fde9fc6426f0aa8c4b6a909fcbb Mon Sep 17 00:00:00 2001 From: "John C. Daub" Date: Wed, 30 Dec 2015 08:10:34 -0600 Subject: [PATCH 3/5] Update tests to adopt the QOS approach. --- Tests/RxCocoaTests/Driver+Test.swift | 2 +- Tests/RxSwiftTests/Tests/Observable+BlockingTest.swift | 10 +++++----- .../Tests/Observable+ConcurrencyTest.swift | 2 +- Tests/RxSwiftTests/Tests/Observable+TimeTest.swift | 10 +++++----- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Tests/RxCocoaTests/Driver+Test.swift b/Tests/RxCocoaTests/Driver+Test.swift index 7738edf3..007483ea 100644 --- a/Tests/RxCocoaTests/Driver+Test.swift +++ b/Tests/RxCocoaTests/Driver+Test.swift @@ -13,7 +13,7 @@ import XCTest import RxTests class DriverTest : RxTest { - var backgroundScheduler = SerialDispatchQueueScheduler(globalConcurrentQueuePriority: .Default) + var backgroundScheduler = SerialDispatchQueueScheduler(globalConcurrentQueueQOS: .Default) override func tearDown() { super.tearDown() diff --git a/Tests/RxSwiftTests/Tests/Observable+BlockingTest.swift b/Tests/RxSwiftTests/Tests/Observable+BlockingTest.swift index c2d84f27..84ffc5aa 100644 --- a/Tests/RxSwiftTests/Tests/Observable+BlockingTest.swift +++ b/Tests/RxSwiftTests/Tests/Observable+BlockingTest.swift @@ -40,7 +40,7 @@ extension ObservableBlockingTest { } func testToArray_withRealScheduler() { - let scheduler = ConcurrentDispatchQueueScheduler(globalConcurrentQueuePriority: .Default) + let scheduler = ConcurrentDispatchQueueScheduler(globalConcurrentQueueQOS: .Default) let array = try! Observable.interval(0.001, scheduler: scheduler) .take(10) @@ -77,7 +77,7 @@ extension ObservableBlockingTest { } func testFirst_withRealScheduler() { - let scheduler = ConcurrentDispatchQueueScheduler(globalConcurrentQueuePriority: .Default) + let scheduler = ConcurrentDispatchQueueScheduler(globalConcurrentQueueQOS: .Default) let array = try! Observable.interval(0.001, scheduler: scheduler) .take(10) @@ -114,7 +114,7 @@ extension ObservableBlockingTest { } func testLast_withRealScheduler() { - let scheduler = ConcurrentDispatchQueueScheduler(globalConcurrentQueuePriority: .Default) + let scheduler = ConcurrentDispatchQueueScheduler(globalConcurrentQueueQOS: .Default) let array = try! Observable.interval(0.001, scheduler: scheduler) .take(10) @@ -174,7 +174,7 @@ extension ObservableBlockingTest { } func testSingle_withRealScheduler() { - let scheduler = ConcurrentDispatchQueueScheduler(globalConcurrentQueuePriority: .Default) + let scheduler = ConcurrentDispatchQueueScheduler(globalConcurrentQueueQOS: .Default) let array = try! Observable.interval(0.001, scheduler: scheduler) .take(1) @@ -271,7 +271,7 @@ extension ObservableBlockingTest { } func testSingle_predicate_withRealScheduler() { - let scheduler = ConcurrentDispatchQueueScheduler(globalConcurrentQueuePriority: .Default) + let scheduler = ConcurrentDispatchQueueScheduler(globalConcurrentQueueQOS: .Default) let array = try! Observable.interval(0.001, scheduler: scheduler) .take(4) diff --git a/Tests/RxSwiftTests/Tests/Observable+ConcurrencyTest.swift b/Tests/RxSwiftTests/Tests/Observable+ConcurrencyTest.swift index f00ea78d..93f26241 100644 --- a/Tests/RxSwiftTests/Tests/Observable+ConcurrencyTest.swift +++ b/Tests/RxSwiftTests/Tests/Observable+ConcurrencyTest.swift @@ -564,7 +564,7 @@ class ObservableConcurrentSchedulerConcurrencyTest: ObservableConcurrencyTestBas class ObservableConcurrentSchedulerConcurrencyTest2 : ObservableConcurrentSchedulerConcurrencyTest { override func createScheduler() -> ImmediateSchedulerType { - return ConcurrentDispatchQueueScheduler(globalConcurrentQueuePriority: .Default) + return ConcurrentDispatchQueueScheduler(globalConcurrentQueueQOS: .Default) } } diff --git a/Tests/RxSwiftTests/Tests/Observable+TimeTest.swift b/Tests/RxSwiftTests/Tests/Observable+TimeTest.swift index 6cf2113d..6e4ba7f0 100644 --- a/Tests/RxSwiftTests/Tests/Observable+TimeTest.swift +++ b/Tests/RxSwiftTests/Tests/Observable+TimeTest.swift @@ -257,7 +257,7 @@ extension ObservableTimeTest { } func test_ThrottleWithRealScheduler() { - let scheduler = ConcurrentDispatchQueueScheduler(globalConcurrentQueuePriority: .Default) + let scheduler = ConcurrentDispatchQueueScheduler(globalConcurrentQueueQOS: .Default) let start = NSDate() @@ -536,7 +536,7 @@ extension ObservableTimeTest { } func testInterval_TimeSpan_Zero_DefaultScheduler() { - let scheduler = SerialDispatchQueueScheduler(globalConcurrentQueuePriority: .Default) + let scheduler = SerialDispatchQueueScheduler(globalConcurrentQueueQOS: .Default) let observer = PrimitiveMockObserver() @@ -586,7 +586,7 @@ extension ObservableTimeTest { } func test_IntervalWithRealScheduler() { - let scheduler = ConcurrentDispatchQueueScheduler(globalConcurrentQueuePriority: .Default) + let scheduler = ConcurrentDispatchQueueScheduler(globalConcurrentQueueQOS: .Default) let start = NSDate() @@ -1093,7 +1093,7 @@ extension ObservableTimeTest { } func testBufferWithTimeOrCount_Default() { - let backgroundScheduler = SerialDispatchQueueScheduler(globalConcurrentQueuePriority: .Default) + let backgroundScheduler = SerialDispatchQueueScheduler(globalConcurrentQueueQOS: .Default) let result = try! Observable.range(start: 1, count: 10, scheduler: backgroundScheduler) .buffer(timeSpan: 1000, count: 3, scheduler: backgroundScheduler) @@ -1293,7 +1293,7 @@ extension ObservableTimeTest { }*/ func windowWithTimeOrCount_Default() { - let backgroundScheduler = SerialDispatchQueueScheduler(globalConcurrentQueuePriority: .Default) + let backgroundScheduler = SerialDispatchQueueScheduler(globalConcurrentQueueQOS: .Default) let result = try! Observable.range(start: 1, count: 10, scheduler: backgroundScheduler) .window(timeSpan: 1000, count: 3, scheduler: backgroundScheduler) From a8890ad7ac5de0107f120f9ffbceeec66b780bc0 Mon Sep 17 00:00:00 2001 From: "John C. Daub" Date: Wed, 30 Dec 2015 09:06:21 -0600 Subject: [PATCH 4/5] QOS is only available on OS X 10.10 and later. --- RxSwift/Schedulers/ConcurrentDispatchQueueScheduler.swift | 1 + RxSwift/Schedulers/SerialDispatchQueueScheduler.swift | 1 + 2 files changed, 2 insertions(+) diff --git a/RxSwift/Schedulers/ConcurrentDispatchQueueScheduler.swift b/RxSwift/Schedulers/ConcurrentDispatchQueueScheduler.swift index 6e65224a..a605593b 100644 --- a/RxSwift/Schedulers/ConcurrentDispatchQueueScheduler.swift +++ b/RxSwift/Schedulers/ConcurrentDispatchQueueScheduler.swift @@ -61,6 +61,7 @@ public class ConcurrentDispatchQueueScheduler: SchedulerType { - parameter globalConcurrentQueueQOS: Target global dispatch queue, by quality of service class. */ + @available(iOS 8, OSX 10.10, *) public convenience init(globalConcurrentQueueQOS: DispatchQueueSchedulerQOS) { let priority: qos_class_t switch globalConcurrentQueueQOS { diff --git a/RxSwift/Schedulers/SerialDispatchQueueScheduler.swift b/RxSwift/Schedulers/SerialDispatchQueueScheduler.swift index 10c9dd00..eb6afb8b 100644 --- a/RxSwift/Schedulers/SerialDispatchQueueScheduler.swift +++ b/RxSwift/Schedulers/SerialDispatchQueueScheduler.swift @@ -99,6 +99,7 @@ public class SerialDispatchQueueScheduler: SchedulerType { - parameter globalConcurrentQueueQOS: Identifier for global dispatch queue with specified quality of service class. - parameter internalSerialQueueName: Custom name for internal serial dispatch queue proxy. */ + @available(iOS 8, OSX 10.10, *) public convenience init(globalConcurrentQueueQOS: DispatchQueueSchedulerQOS, internalSerialQueueName: String = "rx.global_dispatch_queue.serial") { let priority: qos_class_t switch globalConcurrentQueueQOS { From a37dc9f3d340a785b008cc374afde205988c04cb Mon Sep 17 00:00:00 2001 From: "John C. Daub" Date: Wed, 30 Dec 2015 09:30:59 -0600 Subject: [PATCH 5/5] running packager --- Sources/RxSwift/DispatchQueueSchedulerQOS.swift | 1 + 1 file changed, 1 insertion(+) create mode 120000 Sources/RxSwift/DispatchQueueSchedulerQOS.swift diff --git a/Sources/RxSwift/DispatchQueueSchedulerQOS.swift b/Sources/RxSwift/DispatchQueueSchedulerQOS.swift new file mode 120000 index 00000000..c00e8022 --- /dev/null +++ b/Sources/RxSwift/DispatchQueueSchedulerQOS.swift @@ -0,0 +1 @@ +../../RxSwift/Schedulers/DispatchQueueSchedulerQOS.swift \ No newline at end of file