-
Notifications
You must be signed in to change notification settings - Fork 10.5k
/
Copy pathasync_task_cancellation_while_running.swift
101 lines (85 loc) · 2.8 KB
/
async_task_cancellation_while_running.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
// RUN: %target-run-simple-swift( -target %target-swift-5.1-abi-triple %import-libdispatch -parse-as-library) | %FileCheck %s
// REQUIRES: executable_test
// REQUIRES: concurrency
// REQUIRES: libdispatch
// rdar://76038845
// REQUIRES: concurrency_runtime
// UNSUPPORTED: back_deployment_runtime
import Dispatch
let seconds: UInt64 = 1_000_000_000
@available(SwiftStdlib 5.1, *)
func test_detach_cancel_while_child_running() async {
let task: Task<Bool, Error> = Task.detached {
async let childCancelled: Bool = { () -> Bool in
await Task.sleep(3 * seconds)
return Task.isCancelled
}()
let childWasCancelled = await childCancelled
print("child, cancelled: \(childWasCancelled)") // CHECK: child, cancelled: true
let selfWasCancelled = Task.isCancelled
print("self, cancelled: \(selfWasCancelled )") // CHECK: self, cancelled: true
return selfWasCancelled
}
// sleep here, i.e. give the task a moment to start running
await Task.sleep(2 * seconds)
task.cancel()
print("task.cancel()")
let got = try! await task.get()
print("was cancelled: \(got)") // CHECK: was cancelled: true
}
@available(SwiftStdlib 5.1, *)
func test_cancel_while_withTaskCancellationHandler_inflight() async {
let task: Task<Bool, Error> = Task.detached {
await withTaskCancellationHandler {
await Task.sleep(2 * seconds)
print("operation-1")
await Task.sleep(1 * seconds)
print("operation-2")
return Task.isCancelled
} onCancel: {
print("onCancel")
}
}
await Task.sleep(1 * seconds)
// CHECK: task.cancel()
// CHECK: onCancel
// CHECK: operation-1
// CHECK: operation-2
print("task.cancel()")
task.cancel()
let got = try! await task.get()
print("was cancelled: \(got)") // CHECK: was cancelled: true
}
@available(SwiftStdlib 5.1, *)
func test_cancel_while_withTaskCancellationHandler_onlyOnce() async {
let task: Task<Bool, Error> = Task.detached {
await withTaskCancellationHandler {
await Task.sleep(2 * seconds)
await Task.sleep(2 * seconds)
await Task.sleep(2 * seconds)
print("operation-done")
return Task.isCancelled
} onCancel: {
print("onCancel")
}
}
await Task.sleep(1 * seconds)
// CHECK: task.cancel()
// CHECK: onCancel
// onCancel runs only once, even though we attempt to cancel the task many times
// CHECK-NEXT: operation-done
print("task.cancel()")
task.cancel()
task.cancel()
task.cancel()
let got = try! await task.get()
print("was cancelled: \(got)") // CHECK: was cancelled: true
}
@available(SwiftStdlib 5.1, *)
@main struct Main {
static func main() async {
await test_detach_cancel_while_child_running()
await test_cancel_while_withTaskCancellationHandler_inflight()
await test_cancel_while_withTaskCancellationHandler_onlyOnce()
}
}