Closing Channels in Chapel

In Chapel, we can demonstrate closing channels using a similar concept called synchronization variables. While Chapel doesn’t have explicit channels like Go, we can use sync variables to achieve similar functionality.

use IO;

// In this example, we'll use a sync variable to communicate work
// from the main task to a worker task. When we have no more jobs
// for the worker, we'll set the sync variable to signal completion.

proc main() {
    var jobs: sync int;
    var done: sync bool;

    // Here's the worker task. It repeatedly reads from the 'jobs'
    // sync variable. When the sync variable is set to -1, it knows
    // that all jobs are completed.
    begin {
        while true {
            const j = jobs.readFE();
            if j != -1 {
                writeln("received job ", j);
            } else {
                writeln("received all jobs");
                done.writeEF(true);
                break;
            }
        }
    }

    // This sends 3 jobs to the worker using the 'jobs' sync variable
    for j in 1..3 {
        jobs.writeEF(j);
        writeln("sent job ", j);
    }
    
    // Signal that all jobs are sent
    jobs.writeEF(-1);
    writeln("sent all jobs");

    // We await the worker using the 'done' sync variable
    done.readFE();

    // In Chapel, we don't need to explicitly check if a sync variable
    // is closed. Once a sync variable is no longer in use, it will be
    // automatically deallocated.
}

To run this Chapel program:

$ chpl closing_channels.chpl
$ ./closing_channels
sent job 1
received job 1
sent job 2
received job 2
sent job 3
received job 3
sent all jobs
received all jobs

In this Chapel version:

  1. We use a sync int variable jobs to simulate a channel for sending jobs.
  2. The done sync variable is used for synchronization between the main task and the worker task.
  3. The worker task is created using the begin statement, which starts a new task.
  4. Instead of closing a channel, we send a special value (-1) to signal that all jobs are done.
  5. The readFE() and writeEF() methods on sync variables are used for synchronized communication between tasks.

Chapel’s sync variables provide a way to achieve synchronized communication between tasks, similar to channels in other languages. While the syntax and exact mechanisms differ, the overall concept of coordinating work between concurrent tasks remains the same.