Using DispatchQueue as actor's serial executor under Linux

I am trying to make an actor backed by serial DispatchQueue so that I can interoperate with legacy queue based code, but the following example working under macOS fails under Linux.

Am I holding it wrong?

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 {

P.S. filed as a bug here: class DispatchSerialQueue not available under Linux · Issue #848 · apple/swift-corelibs-libdispatch · GitHub

import Dispatch?

Nope, the DispatchSerialQueue is simply missing under Linux.

The proper solution to make an actor that uses DispatchQueue as its executor so that it can cooperate with queue based API is for now this:

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
}
2 Likes