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
|
// 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
protocol WithSpecifiedExecutor: Actor {
nonisolated var executor: any SpecifiedExecutor { get }
}
protocol SpecifiedExecutor: SerialExecutor {}
extension WithSpecifiedExecutor {
/// Establishes the WithSpecifiedExecutorExecutor as the serial
/// executor that will coordinate execution for the actor.
nonisolated var unownedExecutor: UnownedSerialExecutor {
executor.asUnownedSerialExecutor()
}
}
final class NaiveQueueExecutor: SpecifiedExecutor, CustomStringConvertible {
let name: String
let queue: DispatchQueue
init(name: String, _ queue: DispatchQueue) {
self.name = name
self.queue = queue
}
public func enqueue(_ job: consuming ExecutorJob) {
print("\(self): enqueue")
let unowned = UnownedJob(job)
queue.sync {
unowned.runSynchronously(on: self.asUnownedSerialExecutor())
}
print("\(self): after run")
}
var description: Swift.String {
"NaiveQueueExecutor(\(name))"
}
}
actor MyActor: WithSpecifiedExecutor {
nonisolated let executor: any SpecifiedExecutor
// Note that we don't have to provide the unownedExecutor in the actor itself.
// We obtain it from the extension on `WithSpecifiedExecutor`.
init(executor: any SpecifiedExecutor) {
self.executor = executor
}
func test(expectedExecutor: some SerialExecutor, expectedQueue: DispatchQueue) {
expectedExecutor.preconditionIsolated("Expected to be on: \(expectedExecutor)")
dispatchPrecondition(condition: .onQueue(expectedQueue))
print("\(Self.self): on executor \(expectedExecutor)")
}
}
@main struct Main {
static func main() async {
print("begin")
let name = "CustomQueue"
let queue = DispatchQueue(label: name)
let one = NaiveQueueExecutor(name: name, queue)
let actor = MyActor(executor: one)
await actor.test(expectedExecutor: one, expectedQueue: queue)
await actor.test(expectedExecutor: one, expectedQueue: queue)
await actor.test(expectedExecutor: one, expectedQueue: queue)
print("end")
}
}
// CHECK: begin
// CHECK-NEXT: NaiveQueueExecutor(CustomQueue): enqueue
// CHECK-NEXT: MyActor: on executor NaiveQueueExecutor(CustomQueue)
// CHECK-NEXT: MyActor: on executor NaiveQueueExecutor(CustomQueue)
// CHECK-NEXT: MyActor: on executor NaiveQueueExecutor(CustomQueue)
// CHECK-NEXT: NaiveQueueExecutor(CustomQueue): after run
// CHECK-NEXT: end
|