1
1
// This file contains the job queue implementation which re-order jobs based on their priority.
2
- // The current implementation is much simple to be easily debugged, but should be re-implemented
3
- // using priority queue ideally.
4
2
5
3
import _CJavaScriptEventLoop
6
4
7
- #if compiler(>=5.5)
8
-
9
5
@available ( macOS 10 . 15 , iOS 13 . 0 , watchOS 6 . 0 , tvOS 13 . 0 , * )
10
6
struct QueueState : Sendable {
11
7
fileprivate var headJob : UnownedJob ? = nil
@@ -14,51 +10,66 @@ struct QueueState: Sendable {
14
10
15
11
@available ( macOS 14 . 0 , iOS 17 . 0 , watchOS 10 . 0 , tvOS 17 . 0 , * )
16
12
extension JavaScriptEventLoop {
13
+ private var queueLock : NSLock {
14
+ NSLock ( )
15
+ }
17
16
18
17
func insertJobQueue( job newJob: UnownedJob ) {
19
- withUnsafeMutablePointer ( to: & queueState. headJob) { headJobPtr in
20
- var position : UnsafeMutablePointer < UnownedJob ? > = headJobPtr
21
- while let cur = position. pointee {
22
- if cur. rawPriority < newJob. rawPriority {
23
- newJob. nextInQueue ( ) . pointee = cur
24
- position. pointee = newJob
25
- return
26
- }
27
- position = cur. nextInQueue ( )
28
- }
29
- newJob. nextInQueue ( ) . pointee = nil
30
- position. pointee = newJob
31
- }
18
+ queueLock. lock ( )
19
+ defer { queueLock. unlock ( ) }
20
+
21
+ insertJob ( newJob)
32
22
33
- // TODO: use CAS when supporting multi-threaded environment
34
23
if !queueState. isSpinning {
35
- self . queueState. isSpinning = true
24
+ queueState. isSpinning = true
36
25
JavaScriptEventLoop . shared. queueMicrotask {
37
26
self . runAllJobs ( )
38
27
}
39
28
}
40
29
}
41
30
31
+ private func insertJob( _ newJob: UnownedJob ) {
32
+ var current = queueState. headJob
33
+ var previous : UnownedJob ? = nil
34
+
35
+ while let cur = current, cur. rawPriority >= newJob. rawPriority {
36
+ previous = cur
37
+ current = cur. nextInQueue ( ) . pointee
38
+ }
39
+
40
+ newJob. nextInQueue ( ) . pointee = current
41
+ if let prev = previous {
42
+ prev. nextInQueue ( ) . pointee = newJob
43
+ } else {
44
+ queueState. headJob = newJob
45
+ }
46
+ }
47
+
42
48
func runAllJobs( ) {
43
49
assert ( queueState. isSpinning)
44
50
45
- while let job = self . claimNextFromQueue ( ) {
46
- #if compiler(>=5.9)
47
- job. runSynchronously ( on: self . asUnownedSerialExecutor ( ) )
48
- #else
49
- job. _runSynchronously ( on: self . asUnownedSerialExecutor ( ) )
50
- #endif
51
+ while let job = claimNextFromQueue ( ) {
52
+ executeJob ( job)
51
53
}
52
54
53
55
queueState. isSpinning = false
54
56
}
55
57
58
+ private func executeJob( _ job: UnownedJob ) {
59
+ #if compiler(>=5.9)
60
+ job. runSynchronously ( on: self . asUnownedSerialExecutor ( ) )
61
+ #else
62
+ job. _runSynchronously ( on: self . asUnownedSerialExecutor ( ) )
63
+ #endif
64
+ }
65
+
56
66
func claimNextFromQueue( ) -> UnownedJob ? {
57
- if let job = self . queueState. headJob {
58
- self . queueState. headJob = job. nextInQueue ( ) . pointee
59
- return job
60
- }
61
- return nil
67
+ queueLock. lock ( )
68
+ defer { queueLock. unlock ( ) }
69
+
70
+ guard let job = queueState. headJob else { return nil }
71
+ queueState. headJob = job. nextInQueue ( ) . pointee
72
+ return job
62
73
}
63
74
}
64
75
@@ -75,21 +86,17 @@ fileprivate extension UnownedJob {
75
86
var rawPriority : UInt32 { flags. priority }
76
87
77
88
func nextInQueue( ) -> UnsafeMutablePointer < UnownedJob ? > {
78
- return withUnsafeMutablePointer ( to: & asImpl( ) . pointee. SchedulerPrivate. 0 ) { rawNextJobPtr in
79
- let nextJobPtr = UnsafeMutableRawPointer ( rawNextJobPtr) . bindMemory ( to: UnownedJob ? . self, capacity: 1 )
80
- return nextJobPtr
89
+ withUnsafeMutablePointer ( to: & asImpl( ) . pointee. SchedulerPrivate. 0 ) { rawNextJobPtr in
90
+ UnsafeMutableRawPointer ( rawNextJobPtr) . bindMemory ( to: UnownedJob ? . self, capacity: 1 )
81
91
}
82
92
}
83
-
84
93
}
85
94
86
95
fileprivate struct JobFlags {
87
96
var bits : UInt32 = 0
88
97
89
- var priority : UInt32 {
90
- get {
91
- ( bits & 0xFF00 ) >> 8
98
+ var priority : UInt32 {
99
+ ( bits & 0xFF00 ) >> 8
92
100
}
93
- }
94
101
}
95
- #endif
102
+ #endif
0 commit comments