swiftlang / swift-corelibs-libdispatch

The libdispatch Project, (a.k.a. Grand Central Dispatch), for concurrency on multicore hardware
swift.org
Apache License 2.0
2.47k stars 460 forks source link

class DispatchSerialQueue not available under Linux #848

Open mman opened 1 week ago

mman commented 1 week ago

Probably another inconsistency, but the following code creating an actor backed by serial DispatchQueue works on macOS and does not compile under Linux:

public actor MyActor {
    let queue = DispatchSerialQueue(label: "actorQueue")

    nonisolated public var unownedExecutor: UnownedSerialExecutor {
        queue.asUnownedSerialExecutor()
    }
}

Under Linux it produces the following error:

/src/Sources/Test/test.swift:63:17: error: cannot find 'DispatchSerialQueue' in scope
 61 | public actor MyActor {
 62 |     let logger: Logger
 63 |     let queue = DispatchSerialQueue(label: "relayQueue")
    |                 `- error: cannot find 'DispatchSerialQueue' in scope
 64 | 
 65 |     nonisolated public var unownedExecutor: UnownedSerialExecutor {
mman commented 1 week ago

For anybody reaching this bug. For the moment the proper solution under Linux seems to be:

actor X {
    let queue = DispatchQueue(label: "queue")
    private let executor: DispatchQueueExecutor

    final class DispatchQueueExecutor: SerialExecutor {
         private let queue: DispatchQueue

         init(queue: DispatchQueue) {
             self.queue = queue
         }

         func enqueue(_ job: UnownedJob) {
             self.queue.async {
                 job.runSynchronously(on: self.asUnownedSerialExecutor())
             }
         }

         func asUnownedSerialExecutor() -> UnownedSerialExecutor {
             UnownedSerialExecutor(ordinary: self)
         }

        func checkIsolated() {
            dispatchPrecondition(condition: .onQueue(self.queue))
        }
    }

    nonisolated public var unownedExecutor: UnownedSerialExecutor {
        executor.asUnownedSerialExecutor()
    }

    init() {
        self.executor = DispatchQueueExecutor(queue: queue)
    }

    /// remaining logic
}