forked from aleclarson/dispatcher
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathDispatchQueue.swift
82 lines (60 loc) · 2.23 KB
/
DispatchQueue.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import Foundation
open class DispatcherQueue {
private static let Label = "com.mobilenatives.dispatcher"
// MARK: Public
open let isConcurrent: Bool
open var isCurrent: Bool {
return DispatchQueue.getSpecific(key: kCurrentQueue) == getMutablePointer(self)
}
open func async (_ callback: @escaping (Void) -> Void) {
dispatch_queue.async(execute: callback)
}
open func sync (_ callback: (Void) -> Void) {
if isCurrent { callback(); return } // prevent deadlocks!
dispatch_queue.sync(execute: callback)
}
open func async <T> (_ callback: @escaping (T) -> Void) -> (T) -> Void {
return { [weak self] value in
guard let strongSelf = self else { return }
strongSelf.async { callback(value) }
}
}
open func sync <T> (_ callback: @escaping (T) -> Void) -> (T) -> Void {
return { [weak self] value in
guard let strongSelf = self else { return }
strongSelf.sync { callback(value) }
}
}
open let dispatch_queue: DispatchQueue
// MARK: Internal
init (queue: DispatchQueue) {
isConcurrent = false
dispatch_queue = queue
remember()
}
init (qos: DispatchQoS.QoSClass) {
isConcurrent = true
dispatch_queue = DispatchQueue.global(qos: qos)
remember()
}
init (concurrent: Bool) {
isConcurrent = concurrent
// https://bugs.swift.org/browse/SR-1859
if #available(iOS 10.0, *) {
dispatch_queue = DispatchQueue(label: DispatcherQueue.Label, attributes: isConcurrent ? [DispatchQueue.Attributes.concurrent, DispatchQueue.Attributes.initiallyInactive] : [DispatchQueue.Attributes.initiallyInactive])
} else {
dispatch_queue = isConcurrent ? DispatchQueue(label: DispatcherQueue.Label, attributes: [DispatchQueue.Attributes.concurrent]) : DispatchQueue(label: DispatcherQueue.Label)
}
remember()
}
func remember () {
guard let mutablePointer = getMutablePointer(self) else {
return
}
dispatch_queue.setSpecific(key: kCurrentQueue, value: mutablePointer)
}
}
var kCurrentQueue = DispatchSpecificKey<UnsafeMutableRawPointer>()
func getMutablePointer (_ object: AnyObject) -> UnsafeMutableRawPointer? {
return UnsafeMutableRawPointer(bitPattern: Int(bitPattern: ObjectIdentifier(object)))
}