Non Blocking Channel Operations in Chapel

Basic sends and receives on channels are blocking in Chapel. However, we can use select statements with a otherwise clause to implement non-blocking operations, including non-blocking multi-way selects.

use IO;

proc main() {
    var messages: channel(string);
    var signals: channel(bool);

    // Here's a non-blocking receive. If a value is
    // available on `messages` then `select` will take
    // the `messages.recv()` case with that value. If not
    // it will immediately take the `otherwise` case.
    select {
        when var msg = messages.recv() {
            writeln("received message ", msg);
        }
        otherwise {
            writeln("no message received");
        }
    }

    // A non-blocking send works similarly. Here `msg`
    // cannot be sent to the `messages` channel, because
    // the channel has no buffer and there is no receiver.
    // Therefore the `otherwise` case is selected.
    var msg = "hi";
    select {
        when messages.send(msg) {
            writeln("sent message ", msg);
        }
        otherwise {
            writeln("no message sent");
        }
    }

    // We can use multiple `when` clauses above the `otherwise`
    // clause to implement a multi-way non-blocking
    // select. Here we attempt non-blocking receives
    // on both `messages` and `signals`.
    select {
        when var msg = messages.recv() {
            writeln("received message ", msg);
        }
        when var sig = signals.recv() {
            writeln("received signal ", sig);
        }
        otherwise {
            writeln("no activity");
        }
    }
}

To run the program:

$ chpl non_blocking_channel_operations.chpl
$ ./non_blocking_channel_operations
no message received
no message sent
no activity

In Chapel, channels are used for communication between tasks, similar to channels in other languages. The select statement in Chapel allows for non-blocking operations on channels.

The when clauses in the select statement correspond to different channel operations, and the otherwise clause is executed if none of the channel operations are ready.

Note that Chapel’s syntax for channel operations is slightly different from some other languages. For example, we use channel.recv() for receiving and channel.send(value) for sending, instead of arrow notations.

Also, Chapel doesn’t have a built-in make function for creating channels. Instead, channels are declared with their type, and they’re automatically initialized.

This example demonstrates how to perform non-blocking operations on channels in Chapel, which can be useful in concurrent programming scenarios where you don’t want your program to block on channel operations.