-
Notifications
You must be signed in to change notification settings - Fork 10.5k
/
Copy pathcustom_executors_complex_equality_subclass.swift
110 lines (90 loc) · 3.4 KB
/
custom_executors_complex_equality_subclass.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
// RUN: %target-run-simple-swift( -Xfrontend -enable-experimental-move-only -Xfrontend -disable-availability-checking %import-libdispatch -parse-as-library) | %FileCheck %s
// REQUIRES: concurrency
// REQUIRES: executable_test
// REQUIRES: libdispatch
// rdar://106849189 move-only types should be supported in freestanding mode
// UNSUPPORTED: freestanding
// UNSUPPORTED: back_deployment_runtime
// REQUIRES: concurrency_runtime
import Dispatch
@_spi(ConcurrencyExecutors) import _Concurrency
class BaseExecutor: SerialExecutor, @unchecked Sendable /* only for testing purposes */ {
let name: String
let queue: DispatchQueue
init(name: String, _ queue: DispatchQueue) {
self.name = name
self.queue = queue
}
func enqueue(_ unowned: UnownedJob) {
fatalError("not implemented in base class")
}
func asUnownedSerialExecutor() -> UnownedSerialExecutor {
let ref = UnownedSerialExecutor(complexEquality: self)
precondition(ref._isComplexEquality, "expected the ref to have complex equality")
return ref
}
func isSameExclusiveExecutionContext(other: BaseExecutor) -> Bool {
if Set([self.name, other.name]) == Set(["left", "right"]) {
// those we consider equal
print("BASE \(BaseExecutor.self).isSameExclusiveExecutionContext: consider \(Self.self)('left') and \(type(of: other))('right') executors as equal context")
return true
} else {
return false
}
}
}
final class LeftExecutor: BaseExecutor {
override init(name: String, _ queue: DispatchQueue) {
super.init(name: name, queue)
}
override func enqueue(_ unowned: UnownedJob) {
print("\(self): enqueue")
queue.sync {
unowned.runSynchronously(on: self.asUnownedSerialExecutor())
}
}
}
final class RightExecutor: BaseExecutor {
override init(name: String, _ queue: DispatchQueue) {
super.init(name: name, queue)
}
override func enqueue(_ unowned: UnownedJob) {
print("\(self): enqueue")
queue.sync {
unowned.runSynchronously(on: self.asUnownedSerialExecutor())
}
}
}
actor MyActor {
nonisolated let executor: BaseExecutor
nonisolated var unownedExecutor: UnownedSerialExecutor {
print("Get executor of \(self): \(executor.asUnownedSerialExecutor())")
return executor.asUnownedSerialExecutor()
}
init(executor: BaseExecutor) {
self.executor = executor
}
func test(expectedExecutor: BaseExecutor, expectedQueue: DispatchQueue) {
expectedExecutor.preconditionIsolated("Expected deep equality to trigger for \(expectedExecutor) and our \(self.executor)")
print("\(Self.self): [\(self.executor.name)] on same context as [\(expectedExecutor.name)]")
}
}
@main struct Main {
static func main() async {
print("begin")
let queue = DispatchQueue(label: "RootQueue")
let one = LeftExecutor(name: "left", queue)
let two = RightExecutor(name: "right", queue)
let actor = MyActor(executor: one)
await actor.test(expectedExecutor: one, expectedQueue: queue)
await actor.test(expectedExecutor: two, expectedQueue: queue)
print("end")
}
}
// CHECK: begin
// CHECK-NEXT: Get executor of main.MyActor
// CHECK-NEXT: main.LeftExecutor: enqueue
// CHECK-NEXT: MyActor: [left] on same context as [left]
// CHECK-NEXT: BASE BaseExecutor.isSameExclusiveExecutionContext: consider LeftExecutor('left') and RightExecutor('right') executors as equal context
// CHECK-NEXT: MyActor: [left] on same context as [right]
// CHECK-NEXT: end