1
1
// RUN: %empty-directory(%t)
2
2
3
- // RUN: %target-build-swift %s -Xfrontend -disable-availability-checking - parse-as-library -o %t/async_task_priority
3
+ // RUN: %target-build-swift %s -parse-as-library -o %t/async_task_priority
4
4
// RUN: %target-codesign %t/async_task_priority
5
5
// RUN: %target-run %t/async_task_priority
6
6
@@ -26,6 +26,7 @@ import Darwin
26
26
@preconcurrency import Dispatch
27
27
import StdlibUnittest
28
28
29
+ @available ( SwiftStdlib 5 . 9 , * )
29
30
func loopUntil( priority: TaskPriority ) async {
30
31
var currentPriority = Task . currentPriority
31
32
while ( currentPriority != priority) {
@@ -39,6 +40,7 @@ func print(_ s: String = "") {
39
40
fputs ( " \( s) \n " , stderr)
40
41
}
41
42
43
+ @available ( SwiftStdlib 5 . 9 , * )
42
44
func expectedBasePri( priority: TaskPriority ) -> TaskPriority {
43
45
let basePri = Task . basePriority!
44
46
print ( " Testing basePri matching expected pri - \( basePri) == \( priority) " )
@@ -54,6 +56,7 @@ func expectedBasePri(priority: TaskPriority) -> TaskPriority {
54
56
return basePri
55
57
}
56
58
59
+ @available ( SwiftStdlib 5 . 9 , * )
57
60
func expectedEscalatedPri( priority: TaskPriority ) -> TaskPriority {
58
61
let curPri = Task . currentPriority
59
62
print ( " Testing escalated matching expected pri - \( curPri) == \( priority) " )
@@ -62,16 +65,19 @@ func expectedEscalatedPri(priority: TaskPriority) -> TaskPriority {
62
65
return curPri
63
66
}
64
67
68
+ @available ( SwiftStdlib 5 . 9 , * )
65
69
func testNestedTaskPriority( basePri: TaskPriority , curPri: TaskPriority ) async {
66
70
let _ = expectedBasePri ( priority: basePri)
67
71
let _ = expectedEscalatedPri ( priority: curPri)
68
72
}
69
73
74
+ @available ( SwiftStdlib 5 . 9 , * )
70
75
func childTaskWaitingForEscalation( sem: DispatchSemaphore , basePri: TaskPriority , curPri : TaskPriority ) async {
71
76
sem. wait ( ) /* Wait to be escalated */
72
77
let _ = await testNestedTaskPriority ( basePri: basePri, curPri: curPri)
73
78
}
74
79
80
+ @available ( SwiftStdlib 5 . 9 , * )
75
81
actor Test {
76
82
private var value = 0
77
83
init ( ) { }
@@ -88,8 +94,7 @@ actor Test {
88
94
semToWait. wait ( ) ;
89
95
90
96
sleep ( 1 )
91
- // TODO: insert a test to verify that thread priority has actually escalated
92
- // to match priExpected
97
+ // FIXME: insert a test to verify that thread priority has actually escalated to match priExpected
93
98
return increment ( )
94
99
}
95
100
@@ -98,17 +103,16 @@ actor Test {
98
103
99
104
@main struct Main {
100
105
static func main( ) async {
101
-
102
- let top_level = detach { /* To detach from main actor when running work */
106
+ let top_level = Task . detached { /* To detach from main actor when running work */
103
107
104
108
let tests = TestSuite ( " Task Priority manipulations " )
105
- if #available( SwiftStdlib 5 . 1 , * ) {
109
+ if #available( SwiftStdlib 5 . 9 , * ) {
106
110
107
111
tests. test ( " Basic escalation test when task is running " ) {
108
112
let parentPri = Task . currentPriority
109
113
110
114
let sem = DispatchSemaphore ( value: 0 )
111
- let task = Task ( priority: . background) {
115
+ let task = Task . detached ( priority: . background) {
112
116
let _ = expectedBasePri ( priority: . background)
113
117
114
118
// Wait until task is running before asking to be escalated
@@ -136,15 +140,15 @@ actor Test {
136
140
137
141
tests. test ( " Structured concurrency priority propagation " ) {
138
142
let task = Task ( priority: . background) {
139
- await loopUntil ( priority: . default )
143
+ await loopUntil ( priority: . medium )
140
144
141
145
let basePri = expectedBasePri ( priority: . background)
142
- let curPri = expectedEscalatedPri ( priority: . default )
146
+ let curPri = expectedEscalatedPri ( priority: . medium )
143
147
144
148
// Structured concurrency via async let, escalated priority of
145
149
// parent should propagate
146
150
print ( " Testing propagation for async let structured concurrency child " )
147
- async let child = testNestedTaskPriority ( basePri: basePri, curPri: curPri)
151
+ async let child : ( ) = testNestedTaskPriority ( basePri: basePri, curPri: curPri)
148
152
await child
149
153
150
154
let dispatchGroup = DispatchGroup ( )
@@ -177,11 +181,11 @@ actor Test {
177
181
}
178
182
179
183
tests. test ( " Unstructured tasks priority propagation " ) {
180
- let task = Task ( priority : . background) {
181
- await loopUntil ( priority: . default )
184
+ let task = Task . detached ( priority: . background) {
185
+ await loopUntil ( priority: . medium )
182
186
183
187
let basePri = expectedBasePri ( priority: . background)
184
- let _ = expectedEscalatedPri ( priority: . default )
188
+ let _ = expectedEscalatedPri ( priority: . medium )
185
189
186
190
let group = DispatchGroup ( )
187
191
@@ -190,7 +194,6 @@ actor Test {
190
194
let _ = Task {
191
195
let _ = await testNestedTaskPriority ( basePri: basePri, curPri: basePri)
192
196
group. leave ( )
193
- return
194
197
}
195
198
196
199
// Wait for unstructured task to finish running, don't await it
@@ -201,72 +204,70 @@ actor Test {
201
204
await task. value // Escalate task BG->DEF
202
205
}
203
206
204
- tests. test ( " Task escalation propagation to SC children " ) {
205
- // Create a task tree and then escalate the parent
206
- let parentPri = Task . currentPriority
207
- let basePri : TaskPriority = . background
208
-
209
- let sem = DispatchSemaphore ( value: 0 )
210
- let sem2 = DispatchSemaphore ( value : 0 )
207
+ tests. test ( " Task escalation propagation to structured concurrency child tasks " ) {
208
+ // Create a task tree and then escalate the parent
209
+ let parentPri = Task . currentPriority
210
+ let basePri : TaskPriority = . background
211
211
212
- let task = Task ( priority: basePri) {
212
+ let sem = DispatchSemaphore ( value: 0 )
213
+ let sem2 = DispatchSemaphore ( value: 0 )
213
214
214
- async let child = childTaskWaitingForEscalation ( sem: sem2, basePri: basePri, curPri: parentPri)
215
+ let task = Task . detached ( priority: basePri) {
216
+ async let child = childTaskWaitingForEscalation ( sem: sem2, basePri: basePri, curPri: parentPri)
215
217
216
- await withTaskGroup ( of : Void . self , returning : Void . self ) { group in
217
- group. addTask {
218
- let _ = await childTaskWaitingForEscalation ( sem: sem2, basePri: basePri, curPri: parentPri)
219
- }
220
- group. addTask ( priority: . utility) {
221
- let _ = await childTaskWaitingForEscalation ( sem: sem2, basePri: . utility, curPri: parentPri)
222
- }
218
+ await withTaskGroup { group in
219
+ group. addTask {
220
+ let _ = await childTaskWaitingForEscalation ( sem: sem2, basePri: basePri, curPri: parentPri)
221
+ }
222
+ group. addTask ( priority: . utility) {
223
+ let _ = await childTaskWaitingForEscalation ( sem: sem2, basePri: . utility, curPri: parentPri)
224
+ }
223
225
224
- sem. signal ( ) // Ask for escalation after creating full task tree
225
- sleep ( 1 )
226
+ sem. signal ( ) // Ask for escalation after creating full task tree
227
+ sleep ( 1 )
226
228
227
- let _ = expectedBasePri ( priority: basePri)
228
- let _ = expectedEscalatedPri ( priority: parentPri)
229
+ let _ = expectedBasePri ( priority: basePri)
230
+ let _ = expectedEscalatedPri ( priority: parentPri)
229
231
230
- sem2. signal ( ) // Ask async let child to evaluate
231
- sem2. signal ( ) // Ask task group child 1 to evaluate
232
- sem2. signal ( ) // Ask task group child 2 to evaluate
233
- }
232
+ sem2. signal ( ) // Ask async let child to evaluate
233
+ sem2. signal ( ) // Ask task group child 1 to evaluate
234
+ sem2. signal ( ) // Ask task group child 2 to evaluate
234
235
}
236
+ }
235
237
236
- // Wait until children are created and then ask for escalation of
237
- // top level
238
- sem. wait ( )
239
- await task. value
238
+ // Wait until children are created and then ask for escalation of top level
239
+ sem. wait ( )
240
+ await task. value
240
241
}
241
242
242
243
tests. test ( " Simple task escalation to a future " ) {
243
- let task1Pri : TaskPriority = . background
244
- let task2Pri : TaskPriority = . utility
245
- let parentPri : TaskPriority = Task . currentPriority
246
- print ( " Top level task current priority = \( parentPri) " )
244
+ let task1Pri : TaskPriority = . background
245
+ let task2Pri : TaskPriority = . utility
246
+ let parentPri : TaskPriority = Task . currentPriority
247
+ print ( " Top level task current priority = \( parentPri) " )
247
248
248
- // After task2 has suspended waiting for task1, escalating task2
249
- // should cause task1 to escalate
249
+ // After task2 has suspended waiting for task1,
250
+ // escalating task2 should cause task1 to escalate
250
251
251
- let task1 = Task ( priority: task1Pri) {
252
- // Wait until task2 has blocked on task1 and escalated it
253
- sleep ( 1 )
254
- expectedEscalatedPri ( priority: task2Pri)
252
+ let task1 = Task . detached ( priority: task1Pri) {
253
+ // Wait until task2 has blocked on task1 and escalated it
254
+ sleep ( 1 )
255
+ _ = expectedEscalatedPri ( priority: task2Pri)
255
256
256
- // Wait until task2 itself has been escalated
257
- sleep ( 5 )
258
- expectedEscalatedPri ( priority: parentPri)
259
- }
257
+ // Wait until task2 itself has been escalated
258
+ sleep ( 5 )
259
+ _ = expectedEscalatedPri ( priority: parentPri)
260
+ }
260
261
261
- let task2 = Task ( priority: task2Pri) {
262
- await task1. value
263
- }
262
+ let task2 = Task . detached ( priority: task2Pri) {
263
+ await task1. value
264
+ }
264
265
265
- // Wait for task2 and task1 to run and for task2 to now block on
266
- // task1
267
- sleep ( 3 )
266
+ // Wait for task2 and task1 to run and for task2 to now block on
267
+ // task1
268
+ sleep ( 3 )
268
269
269
- await task2. value
270
+ await task2. value
270
271
}
271
272
272
273
tests. test ( " Simple task escalation to a future 2 " ) {
@@ -283,11 +284,11 @@ actor Test {
283
284
284
285
sleep ( 1 ) // Wait for task1 to start running
285
286
286
- let task2 = Task ( priority: task2Pri) {
287
- func childTask( ) async {
288
- await task1. value
289
- }
290
- async let child = childTask ( )
287
+ let task2 = Task . detached ( priority: task2Pri) {
288
+ @ Sendable func childTask( ) async {
289
+ await task1. value
290
+ }
291
+ async let child = childTask ( )
291
292
}
292
293
293
294
sleep ( 1 ) // Wait for task2 to start running
@@ -303,15 +304,15 @@ actor Test {
303
304
let sem2 = DispatchSemaphore ( value: 0 )
304
305
let testActor = Test ( )
305
306
306
- let task1 = Task ( priority: task1Pri) {
307
- expectedBasePri ( priority: task1Pri) ;
307
+ let task1 = Task . detached ( priority: task1Pri) {
308
+ _ = expectedBasePri ( priority: task1Pri)
308
309
await testActor. blockActorThenIncrement ( semToSignal: sem1, semToWait: sem2, priExpected: parentPri) ;
309
310
}
310
311
311
312
sem1. wait ( ) // Wait until task1 is on the actor
312
313
313
314
let task2 = Task ( priority: task2Pri) {
314
- expectedBasePri ( priority: task2Pri) ;
315
+ _ = expectedBasePri ( priority: task2Pri)
315
316
await testActor. increment ( )
316
317
}
317
318
0 commit comments