Skip to content

Commit e1754a3

Browse files
authored
Merge pull request #1 from asalom/feature/swift_3.0
swift 3.0
2 parents 98fb989 + 83b6360 commit e1754a3

File tree

8 files changed

+141
-117
lines changed

8 files changed

+141
-117
lines changed

DispatchGroup.swift

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,47 +2,49 @@
22
import CoreGraphics
33
import Dispatch
44

5-
public typealias Group = DispatchGroup
6-
7-
public class DispatchGroup {
5+
open class DispatcherGroup {
86

97
public init (_ tasks: Int = 0) {
108
for _ in 0..<tasks { ++self }
119
}
1210

13-
public private(set) var tasks = 0
11+
open fileprivate(set) var tasks = 0
1412

15-
public let dispatch_group = dispatch_group_create()
13+
open let dispatch_group = DispatchGroup()
1614

17-
public func done (callback: Void -> Void) {
18-
dispatch_group_notify(dispatch_group, gcd.current.dispatch_queue, callback)
15+
open func done (_ callback: @escaping (Void) -> Void) {
16+
guard let current = gcd.current else {
17+
return
18+
}
19+
20+
dispatch_group.notify(queue: current.dispatch_queue, execute: callback)
1921
}
2022

21-
public func wait (delay: CGFloat, _ callback: Void -> Void) {
22-
dispatch_group_wait(dispatch_group, dispatch_time(DISPATCH_TIME_NOW, Int64(delay * CGFloat(NSEC_PER_SEC))))
23+
open func wait (_ delay: CGFloat, _ callback: (Void) -> Void) {
24+
let _ = dispatch_group.wait(timeout: DispatchTime.now() + Double(Int64(delay * CGFloat(NSEC_PER_SEC))) / Double(NSEC_PER_SEC))
2325
}
2426

2527
deinit { assert(tasks == 0, "A DispatchGroup cannot be deallocated when tasks is greater than zero!") }
2628
}
2729

28-
public prefix func ++ (group: DispatchGroup) {
30+
public prefix func ++ (group: DispatcherGroup) {
2931
objc_sync_enter(group)
3032
group.tasks += 1
31-
dispatch_group_enter(group.dispatch_group)
33+
group.dispatch_group.enter()
3234
objc_sync_exit(group)
3335
}
3436

35-
public prefix func -- (group: DispatchGroup) {
37+
public prefix func -- (group: DispatcherGroup) {
3638
objc_sync_enter(group)
3739
group.tasks -= 1
38-
dispatch_group_leave(group.dispatch_group)
40+
group.dispatch_group.leave()
3941
objc_sync_exit(group)
4042
}
4143

42-
public postfix func ++ (group: DispatchGroup) {
44+
public postfix func ++ (group: DispatcherGroup) {
4345
++group
4446
}
4547

46-
public postfix func -- (group: DispatchGroup) {
48+
public postfix func -- (group: DispatcherGroup) {
4749
--group
4850
}

DispatchQueue.swift

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,82 @@
11

22
import Foundation
33

4-
public typealias Queue = DispatchQueue
5-
6-
public class DispatchQueue {
4+
open class DispatcherQueue {
75

6+
private static let Label = "com.mobilenatives.dispatcher"
7+
88
// MARK: Public
99

10-
public let isConcurrent: Bool
10+
open let isConcurrent: Bool
1111

12-
public var isCurrent: Bool { return dispatch_get_specific(&kCurrentQueue) == getMutablePointer(self) }
12+
open var isCurrent: Bool {
13+
return DispatchQueue.getSpecific(key: kCurrentQueue) == getMutablePointer(self)
14+
}
1315

14-
public func async (callback: Void -> Void) {
15-
dispatch_async(dispatch_queue) { callback() }
16+
open func async (_ callback: @escaping (Void) -> Void) {
17+
dispatch_queue.async(execute: callback)
1618
}
1719

18-
public func sync (callback: Void -> Void) {
20+
open func sync (_ callback: (Void) -> Void) {
1921
if isCurrent { callback(); return } // prevent deadlocks!
20-
dispatch_sync(dispatch_queue) { callback() }
22+
dispatch_queue.sync(execute: callback)
2123
}
2224

23-
public func async <T> (callback: T -> Void) -> T -> Void {
25+
open func async <T> (_ callback: @escaping (T) -> Void) -> (T) -> Void {
2426
return { [weak self] value in
25-
if self == nil { return }
26-
self!.async { callback(value) }
27+
guard let strongSelf = self else { return }
28+
strongSelf.async { callback(value) }
2729
}
2830
}
2931

30-
public func sync <T> (callback: T -> Void) -> T -> Void {
32+
open func sync <T> (_ callback: @escaping (T) -> Void) -> (T) -> Void {
3133
return { [weak self] value in
32-
if self == nil { return }
33-
self!.sync { callback(value) }
34+
guard let strongSelf = self else { return }
35+
strongSelf.sync { callback(value) }
3436
}
3537
}
3638

37-
public let dispatch_queue: dispatch_queue_t
39+
open let dispatch_queue: DispatchQueue
3840

3941

4042

4143
// MARK: Internal
4244

43-
init (_ queue: dispatch_queue_t) {
45+
init (queue: DispatchQueue) {
4446
isConcurrent = false
4547
dispatch_queue = queue
4648
remember()
4749
}
48-
49-
init (_ priority: dispatch_queue_priority_t) {
50+
51+
init (qos: DispatchQoS.QoSClass) {
5052
isConcurrent = true
51-
dispatch_queue = dispatch_get_global_queue(priority, 0)
53+
dispatch_queue = DispatchQueue.global(qos: qos)
5254
remember()
5355
}
5456

55-
init (_ concurrent: Bool) {
57+
init (concurrent: Bool) {
5658
isConcurrent = concurrent
57-
dispatch_queue = dispatch_queue_create(nil, isConcurrent ? DISPATCH_QUEUE_CONCURRENT : DISPATCH_QUEUE_SERIAL)
59+
60+
// https://bugs.swift.org/browse/SR-1859
61+
if #available(iOS 10.0, *) {
62+
dispatch_queue = DispatchQueue(label: DispatcherQueue.Label, attributes: isConcurrent ? [DispatchQueue.Attributes.concurrent, DispatchQueue.Attributes.initiallyInactive] : [DispatchQueue.Attributes.initiallyInactive])
63+
} else {
64+
dispatch_queue = isConcurrent ? DispatchQueue(label: DispatcherQueue.Label, attributes: [DispatchQueue.Attributes.concurrent]) : DispatchQueue(label: DispatcherQueue.Label)
65+
}
5866
remember()
5967
}
6068

6169
func remember () {
62-
dispatch_queue_set_specific(dispatch_queue, &kCurrentQueue, getMutablePointer(self), nil)
70+
guard let mutablePointer = getMutablePointer(self) else {
71+
return
72+
}
73+
74+
dispatch_queue.setSpecific(key: kCurrentQueue, value: mutablePointer)
6375
}
6476
}
6577

66-
var kCurrentQueue = 0
78+
var kCurrentQueue = DispatchSpecificKey<UnsafeMutableRawPointer>()
6779

68-
func getMutablePointer (object: AnyObject) -> UnsafeMutablePointer<Void> {
69-
return UnsafeMutablePointer<Void>(bitPattern: Int(ObjectIdentifier(object).uintValue))
80+
func getMutablePointer (_ object: AnyObject) -> UnsafeMutableRawPointer? {
81+
return UnsafeMutableRawPointer(bitPattern: Int(bitPattern: ObjectIdentifier(object)))
7082
}

DispatchTimer.swift

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,13 @@
22
import Foundation
33
import UIKit
44

5-
public typealias Timer = DispatchTimer
5+
open class DispatcherTimer {
66

7-
public class DispatchTimer {
8-
9-
public convenience init (_ delay: CGFloat, _ callback: Void -> Void) {
7+
public convenience init (_ delay: CGFloat, _ callback: @escaping (Void) -> Void) {
108
self.init(delay, 0, callback)
119
}
1210

13-
public init (_ delay: CGFloat, _ tolerance: CGFloat, _ callback: Void -> Void) {
11+
public init (_ delay: CGFloat, _ tolerance: CGFloat, _ callback: @escaping (Void) -> Void) {
1412
self.callback = callback
1513
self.tolerance = tolerance
1614

@@ -20,57 +18,65 @@ public class DispatchTimer {
2018
}
2119

2220
self.callbackQueue = gcd.current
23-
self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue.dispatch_queue)
21+
self.timer = DispatchSource.makeTimerSource(flags: DispatchSource.TimerFlags(rawValue: 0), queue: queue.dispatch_queue)
2422

25-
if !gcd.main.isCurrent { dispatch_set_target_queue(queue.dispatch_queue, gcd.current.dispatch_queue) }
23+
if !gcd.main.isCurrent {
24+
if let dispatch_queue = gcd.current?.dispatch_queue {
25+
queue.dispatch_queue.setTarget(queue: dispatch_queue)
26+
}
27+
}
2628

2729
let delay_ns = delay * CGFloat(NSEC_PER_SEC)
28-
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay_ns))
29-
dispatch_source_set_timer(timer, time, UInt64(delay_ns), UInt64(tolerance * CGFloat(NSEC_PER_SEC)))
30-
dispatch_source_set_event_handler(timer) { [weak self] in let _ = self?.fire() }
31-
dispatch_resume(timer)
30+
let time = DispatchTime.now() + Double(delay)
31+
32+
let interval = DispatchTimeInterval.nanoseconds(Int(delay_ns))
33+
let leeway = DispatchTimeInterval.nanoseconds(Int(UInt64(tolerance * CGFloat(NSEC_PER_SEC))))
34+
35+
timer?.scheduleRepeating(deadline: time, interval: interval, leeway: leeway)
36+
timer?.setEventHandler { [weak self] in let _ = self?.fire() }
37+
timer?.resume()
3238
}
3339

3440
// MARK: Read-only
3541

36-
public let tolerance: CGFloat
42+
open let tolerance: CGFloat
3743

38-
public let callback: Void -> Void
44+
open let callback: (Void) -> Void
3945

4046
// MARK: Instance methods
4147

42-
public func doRepeat (times: UInt! = nil) {
48+
open func doRepeat (_ times: UInt! = nil) {
4349
isRepeating = true
4450
repeatsLeft = times != nil ? Int(times) : -1
4551
}
4652

47-
public func autorelease () {
53+
open func autorelease () {
4854
isAutoReleased = true
4955
autoReleasedTimers[ObjectIdentifier(self)] = self
5056
}
5157

52-
public func fire () {
58+
open func fire () {
5359
if OSAtomicAnd32OrigBarrier(1, &invalidated) == 1 { return }
54-
callbackQueue.sync(callback)
60+
callbackQueue?.sync(callback)
5561
if isRepeating && repeatsLeft > 0 {
5662
repeatsLeft -= 1
5763
}
5864
if !isRepeating || repeatsLeft == 0 { stop() }
5965
}
6066

61-
public func stop () {
67+
open func stop () {
6268
if OSAtomicTestAndSetBarrier(7, &invalidated) { return }
63-
queue.sync({dispatch_source_cancel(self.timer)})
69+
queue.sync({self.timer?.cancel()})
6470
if isAutoReleased { autoReleasedTimers[ObjectIdentifier(self)] = nil }
6571
}
6672

6773
// MARK: Internal
6874

69-
var timer: dispatch_source_t!
75+
var timer: DispatchSourceTimer?
7076

71-
let queue: DispatchQueue = gcd.serial()
77+
let queue: DispatcherQueue = gcd.serial()
7278

73-
var callbackQueue: DispatchQueue!
79+
var callbackQueue: DispatcherQueue?
7480

7581
var invalidated: UInt32 = 0
7682

@@ -85,4 +91,4 @@ public class DispatchTimer {
8591
}
8692
}
8793

88-
var autoReleasedTimers = [ObjectIdentifier:Timer]()
94+
var autoReleasedTimers = [ObjectIdentifier:DispatcherTimer]()

Dispatcher.swift

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,31 @@ import Dispatch
33

44
public let gcd = Dispatcher()
55

6-
public class Dispatcher : DispatchQueue {
6+
public class Dispatcher : DispatcherQueue {
77

8-
public var current: DispatchQueue {
9-
return Unmanaged<DispatchQueue>.fromOpaque(COpaquePointer(dispatch_get_specific(&kCurrentQueue))).takeUnretainedValue()
8+
public var current: DispatcherQueue? {
9+
guard let unsafeRawPoiner = DispatchQueue.getSpecific(key: kCurrentQueue) else {
10+
return nil
11+
}
12+
13+
return Unmanaged<DispatcherQueue>.fromOpaque(unsafeRawPoiner).takeUnretainedValue()
1014
}
1115

12-
public let main = DispatchQueue(dispatch_get_main_queue())
16+
public let main = DispatcherQueue(queue: DispatchQueue.main)
1317

14-
public let high = DispatchQueue(DISPATCH_QUEUE_PRIORITY_HIGH)
18+
public let high = DispatcherQueue(qos: .userInitiated)
1519

16-
public let low = DispatchQueue(DISPATCH_QUEUE_PRIORITY_LOW)
20+
public let low = DispatcherQueue(qos: .utility)
1721

18-
public let background = DispatchQueue(DISPATCH_QUEUE_PRIORITY_BACKGROUND)
22+
public let background = DispatcherQueue(qos: .background)
1923

20-
public func serial () -> DispatchQueue {
21-
return DispatchQueue(false)
24+
public func serial () -> DispatcherQueue {
25+
return DispatcherQueue(concurrent: false)
2226
}
2327

24-
public func concurrent () -> DispatchQueue {
25-
return DispatchQueue(true)
28+
public func concurrent () -> DispatcherQueue {
29+
return DispatcherQueue(concurrent: true)
2630
}
2731

28-
init () { super.init(DISPATCH_QUEUE_PRIORITY_DEFAULT) }
29-
}
32+
init () { super.init(qos: .default) }
33+
}

Dispatcher.xcodeproj/project.pbxproj

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -190,11 +190,11 @@
190190
TargetAttributes = {
191191
1123A3A619F1404E00BF890F = {
192192
CreatedOnToolsVersion = 6.0;
193-
LastSwiftMigration = 0800;
193+
LastSwiftMigration = 0810;
194194
};
195195
1123A3B019F1404F00BF890F = {
196196
CreatedOnToolsVersion = 6.0;
197-
LastSwiftMigration = 0800;
197+
LastSwiftMigration = 0810;
198198
};
199199
};
200200
};
@@ -373,7 +373,7 @@
373373
PRODUCT_NAME = "$(TARGET_NAME)";
374374
SKIP_INSTALL = YES;
375375
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
376-
SWIFT_VERSION = 2.3;
376+
SWIFT_VERSION = 3.0;
377377
TARGETED_DEVICE_FAMILY = "1,2";
378378
VERSIONING_SYSTEM = "apple-generic";
379379
VERSION_INFO_PREFIX = "";
@@ -396,7 +396,7 @@
396396
PRODUCT_BUNDLE_IDENTIFIER = "larson.$(PRODUCT_NAME:rfc1034identifier)";
397397
PRODUCT_NAME = "$(TARGET_NAME)";
398398
SKIP_INSTALL = YES;
399-
SWIFT_VERSION = 2.3;
399+
SWIFT_VERSION = 3.0;
400400
TARGETED_DEVICE_FAMILY = "1,2";
401401
VERSIONING_SYSTEM = "apple-generic";
402402
VERSION_INFO_PREFIX = "";
@@ -418,7 +418,7 @@
418418
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
419419
PRODUCT_BUNDLE_IDENTIFIER = "larson.$(PRODUCT_NAME:rfc1034identifier)";
420420
PRODUCT_NAME = "$(TARGET_NAME)";
421-
SWIFT_VERSION = 2.3;
421+
SWIFT_VERSION = 3.0;
422422
};
423423
name = Debug;
424424
};
@@ -433,7 +433,7 @@
433433
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
434434
PRODUCT_BUNDLE_IDENTIFIER = "larson.$(PRODUCT_NAME:rfc1034identifier)";
435435
PRODUCT_NAME = "$(TARGET_NAME)";
436-
SWIFT_VERSION = 2.3;
436+
SWIFT_VERSION = 3.0;
437437
};
438438
name = Release;
439439
};

0 commit comments

Comments
 (0)