- Notifications
You must be signed in to change notification settings - Fork 10.5k
/
Copy pathasync_task_base_priority.swift
144 lines (116 loc) · 4.36 KB
/
async_task_base_priority.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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
// RUN: %target-run-simple-swift( -Xfrontend -disable-availability-checking %import-libdispatch -parse-as-library )
// REQUIRES: executable_test
// REQUIRES: concurrency
// REQUIRES: libdispatch
// rdar://76038845
// REQUIRES: concurrency_runtime
// UNSUPPORTED: back_deployment_runtime
// UNSUPPORTED: back_deploy_concurrency
// rdar://101077408 – Temporarily disable on watchOS & iOS simulator
// UNSUPPORTED: DARWIN_SIMULATOR=watchos
// UNSUPPORTED: DARWIN_SIMULATOR=ios
// UNSUPPORTED: DARWIN_SIMULATOR=tvos
// UNSUPPORTED: single_threaded_concurrency
import StdlibUnittest
import Dispatch
#if canImport(Darwin)
import Darwin
#elseif canImport(Glibc)
import Glibc
#elseif canImport(Android)
import Android
#elseif os(WASI)
import WASILibc
#elseif os(Windows)
import CRT
import WinSDK
#endif
func loopUntil(priority:TaskPriority)async{
while(Task.currentPriority != priority){
awaitTask.sleep(1_000_000_000)
}
}
func print(_ s:String=""){
fputs("\(s)\n", stderr)
}
func expectedBasePri(priority:TaskPriority)->TaskPriority{
letbasePri=Task.basePriority!
print("Testing basePri matching expected pri - \(basePri) == \(priority)")
expectEqual(basePri, priority)
return basePri
}
func expectedCurrentPri(priority:TaskPriority)->TaskPriority{
letcurPri=Task.currentPriority
print("Testing curPri matching expected pri - \(curPri) == \(priority)")
expectEqual(curPri, priority)
return curPri
}
func testNestedTaskPriority(basePri:TaskPriority, curPri:TaskPriority)async{
let _ =expectedBasePri(priority: basePri)
let _ =expectedCurrentPri(priority: curPri)
}
@mainstructMain{
staticfunc main()async{
lettop_level=detach{ /* To detach from main actor when running work */
lettests=TestSuite("Task base priority")
if #available(SwiftStdlib 5.1,*){
tests.test("Structured concurrency base priority propagation"){
lettask=Task(priority:.background){
awaitloopUntil(priority:.default)
letbasePri=expectedBasePri(priority:.background)
letcurPri=expectedCurrentPri(priority:.default)
// Structured concurrency via async let, escalated priority of
// parent should propagate
print("Testing propagation for async let structured concurrency child")
asyncletchild=testNestedTaskPriority(basePri: basePri, curPri: curPri)
await child
letdispatchGroup=DispatchGroup()
// Structured concurrency via task groups, escalated priority should
// propagate
awaitwithTaskGroup(of:Void.self, returning:Void.self){ group in
dispatchGroup.enter()
group.addTask{
print("Testing propagation for task group regular child")
let _ =awaittestNestedTaskPriority(basePri: basePri, curPri: curPri)
dispatchGroup.leave()
return
}
dispatchGroup.enter()
group.addTask(priority:.utility){
print("Testing propagation for task group child with specified priority")
let _ =awaittestNestedTaskPriority(basePri:.utility, curPri: curPri)
dispatchGroup.leave()
return
}
// Wait for child tasks to finish running, don't await since that
// will escalate them
dispatchGroup.wait()
}
}
await task.value // Escalate task BG->DEF
}
tests.test("Unstructured base priority propagation"){
lettask=Task(priority :.background){
awaitloopUntil(priority:.default)
letbasePri=expectedBasePri(priority:.background)
let _ =expectedCurrentPri(priority:.default)
letgroup=DispatchGroup()
// Create an unstructured task
group.enter()
let _ =Task{
let _ =awaittestNestedTaskPriority(basePri: basePri, curPri: basePri)
group.leave()
return
}
// Wait for unstructured task to finish running, don't await it
// since that will escalate
group.wait()
}
await task.value // Escalate task BG->DEF
}
}
awaitrunAllTestsAsync()
}
await top_level.value
}
}