12
12
13
13
import Swift
14
14
15
+ // Store the Timestamp in the executor private data, if it will fit; otherwise,
16
+ // use the allocator to allocate space for it and stash a pointer in the private
17
+ // data area.
15
18
@available ( SwiftStdlib 6 . 2 , * )
16
19
extension ExecutorJob {
17
- fileprivate var cooperativeExecutorTimestamp : CooperativeExecutor . Timestamp {
20
+ fileprivate var cooperativeExecutorTimestampIsIndirect : Bool {
21
+ return MemoryLayout < ( Int , Int ) > . size
22
+ < MemoryLayout < CooperativeExecutor . Timestamp > . size
23
+ }
24
+
25
+ fileprivate var cooperativeExecutorTimestampPointer : UnsafeMutablePointer < CooperativeExecutor . Timestamp > {
18
26
get {
27
+ assert ( cooperativeExecutorTimestampIsIndirect)
19
28
return unsafe withUnsafeExecutorPrivateData {
20
- return unsafe $0. assumingMemoryBound (
21
- to : CooperativeExecutor . Timestamp . self
22
- ) [ 0 ]
29
+ unsafe $0. withMemoryRebound ( to : UnsafeMutablePointer < CooperativeExecutor . Timestamp > . self ) {
30
+ return unsafe $0 [ 0 ]
31
+ }
23
32
}
24
33
}
25
34
set {
35
+ assert ( cooperativeExecutorTimestampIsIndirect)
26
36
unsafe withUnsafeExecutorPrivateData {
27
- unsafe $0. withMemoryRebound ( to: CooperativeExecutor . Timestamp. self) {
37
+ unsafe $0. withMemoryRebound ( to: UnsafeMutablePointer < CooperativeExecutor . Timestamp> . self ) {
28
38
unsafe $0[ 0 ] = newValue
29
39
}
30
40
}
31
41
}
32
42
}
43
+
44
+ fileprivate var cooperativeExecutorTimestamp : CooperativeExecutor . Timestamp {
45
+ get {
46
+ if cooperativeExecutorTimestampIsIndirect {
47
+ let ptr = unsafe cooperativeExecutorTimestampPointer
48
+ return unsafe ptr. pointee
49
+ } else {
50
+ return unsafe withUnsafeExecutorPrivateData {
51
+ return unsafe $0. assumingMemoryBound (
52
+ to: CooperativeExecutor . Timestamp. self
53
+ ) [ 0 ]
54
+ }
55
+ }
56
+ }
57
+ set {
58
+ if cooperativeExecutorTimestampIsIndirect {
59
+ let ptr = unsafe cooperativeExecutorTimestampPointer
60
+ unsafe ptr. pointee = newValue
61
+ } else {
62
+ unsafe withUnsafeExecutorPrivateData {
63
+ unsafe $0. withMemoryRebound ( to: CooperativeExecutor . Timestamp. self) {
64
+ unsafe $0[ 0 ] = newValue
65
+ }
66
+ }
67
+ }
68
+ }
69
+ }
70
+
71
+ fileprivate mutating func setupCooperativeExecutorTimestamp( ) {
72
+ // If a Timestamp won't fit, allocate
73
+ if cooperativeExecutorTimestampIsIndirect {
74
+ let ptr = unsafe allocator! . allocate ( as: CooperativeExecutor . Timestamp. self)
75
+ unsafe self. cooperativeExecutorTimestampPointer = ptr
76
+ }
77
+ }
78
+
79
+ fileprivate mutating func clearCooperativeExecutorTimestamp( ) {
80
+ // If a Timestamp won't fit, deallocate
81
+ if cooperativeExecutorTimestampIsIndirect {
82
+ let ptr = unsafe self. cooperativeExecutorTimestampPointer
83
+ unsafe allocator! . deallocate ( ptr)
84
+ }
85
+ }
33
86
}
34
87
35
88
/// A co-operative executor that can be used as the main executor or as a
@@ -131,6 +184,7 @@ extension CooperativeExecutor: SchedulableExecutor {
131
184
let duration = Duration ( from: clock. convert ( from: delay) !)
132
185
let deadline = self . currentTime + duration
133
186
187
+ job. setupCooperativeExecutorTimestamp ( )
134
188
job. cooperativeExecutorTimestamp = deadline
135
189
waitQueue. push ( UnownedJob ( job) )
136
190
}
@@ -150,6 +204,8 @@ extension CooperativeExecutor: RunLoopExecutor {
150
204
while let job = waitQueue. pop ( when: {
151
205
ExecutorJob ( $0) . cooperativeExecutorTimestamp <= now
152
206
} ) {
207
+ var theJob = ExecutorJob ( job)
208
+ theJob. clearCooperativeExecutorTimestamp ( )
153
209
runQueue. push ( job)
154
210
}
155
211
0 commit comments