mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
145 lines
4.4 KiB
Swift
145 lines
4.4 KiB
Swift
// 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) {
|
||
await Task.sleep(1_000_000_000)
|
||
}
|
||
}
|
||
|
||
func print(_ s: String = "") {
|
||
fputs("\(s)\n", stderr)
|
||
}
|
||
|
||
func expectedBasePri(priority: TaskPriority) -> TaskPriority {
|
||
let basePri = Task.basePriority!
|
||
|
||
print("Testing basePri matching expected pri - \(basePri) == \(priority)")
|
||
expectEqual(basePri, priority)
|
||
return basePri
|
||
}
|
||
|
||
func expectedCurrentPri(priority: TaskPriority) -> TaskPriority {
|
||
let curPri = 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)
|
||
}
|
||
|
||
@main struct Main {
|
||
static func main() async {
|
||
|
||
let top_level = detach { /* To detach from main actor when running work */
|
||
|
||
let tests = TestSuite("Task base priority")
|
||
if #available(SwiftStdlib 5.1, *) {
|
||
|
||
tests.test("Structured concurrency base priority propagation") {
|
||
let task = Task(priority: .background) {
|
||
await loopUntil(priority: .default)
|
||
|
||
let basePri = expectedBasePri(priority: .background)
|
||
let curPri = expectedCurrentPri(priority: .default)
|
||
|
||
// Structured concurrency via async let, escalated priority of
|
||
// parent should propagate
|
||
print("Testing propagation for async let structured concurrency child")
|
||
async let child = testNestedTaskPriority(basePri: basePri, curPri: curPri)
|
||
await child
|
||
|
||
let dispatchGroup = DispatchGroup()
|
||
// Structured concurrency via task groups, escalated priority should
|
||
// propagate
|
||
await withTaskGroup(of: Void.self, returning: Void.self) { group in
|
||
dispatchGroup.enter()
|
||
group.addTask {
|
||
print("Testing propagation for task group regular child")
|
||
let _ = await testNestedTaskPriority(basePri: basePri, curPri: curPri)
|
||
dispatchGroup.leave()
|
||
return
|
||
}
|
||
|
||
dispatchGroup.enter()
|
||
group.addTask(priority: .utility) {
|
||
print("Testing propagation for task group child with specified priority")
|
||
let _ = await testNestedTaskPriority(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") {
|
||
let task = Task(priority : .background) {
|
||
await loopUntil(priority: .default)
|
||
|
||
let basePri = expectedBasePri(priority: .background)
|
||
let _ = expectedCurrentPri(priority: .default)
|
||
|
||
let group = DispatchGroup()
|
||
|
||
// Create an unstructured task
|
||
group.enter()
|
||
let _ = Task {
|
||
let _ = await testNestedTaskPriority(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
|
||
}
|
||
|
||
}
|
||
await runAllTestsAsync()
|
||
}
|
||
|
||
await top_level.value
|
||
}
|
||
}
|