Non Blocking Channel Operations in Swift

import Foundation

let messages = DispatchQueue(label: "messages")
let signals = DispatchQueue(label: "signals")

// Here's a non-blocking receive. If a value is
// available on `messages` then the `messages.sync` block
// will execute. If not, it will immediately take the `else` case.
if messages.sync(execute: { () -> String? in
    // Simulating a non-blocking receive
    return nil
}) != nil {
    print("received message")
} else {
    print("no message received")
}

// A non-blocking send works similarly. Here `msg`
// cannot be sent to the `messages` queue, because
// there is no receiver. Therefore the `else` case is selected.
let msg = "hi"
if messages.sync(execute: { () -> Bool in
    // Simulating a non-blocking send
    return false
}) {
    print("sent message", msg)
} else {
    print("no message sent")
}

// We can use multiple conditions to implement a multi-way
// non-blocking select. Here we attempt non-blocking receives
// on both `messages` and `signals`.
if let message = messages.sync(execute: { () -> String? in
    // Simulating a non-blocking receive
    return nil
}) {
    print("received message", message)
} else if let signal = signals.sync(execute: { () -> Bool? in
    // Simulating a non-blocking receive
    return nil
}) {
    print("received signal", signal)
} else {
    print("no activity")
}

This Swift code demonstrates non-blocking operations similar to the original example. However, Swift doesn’t have built-in channels or a select statement like Go does. Instead, we use DispatchQueue to simulate similar behavior.

In this example:

  1. We create two DispatchQueue instances to represent our channels.

  2. For non-blocking receives, we use sync on the queue and return nil to simulate an empty channel. If a value is returned, it’s treated as a successful receive.

  3. For non-blocking sends, we use sync on the queue and return false to simulate a failed send. Returning true would indicate a successful send.

  4. The multi-way select is simulated using multiple if-else conditions, each trying to receive from a different queue.

To run this program:

$ swift non-blocking-operations.swift
no message received
no message sent
no activity

This example demonstrates how to perform non-blocking operations in Swift, although the exact semantics differ from Go’s channels. In real-world Swift applications, you might use more sophisticated concurrency primitives like OperationQueue, DispatchGroup, or the new structured concurrency features introduced in Swift 5.5.