Closing Channels in Perl

In Perl, we don’t have built-in channels or goroutines, but we can simulate similar behavior using threads and queues. We’ll use the Thread::Queue module to create a job queue and threads to create worker threads.

use strict;
use warnings;
use threads;
use Thread::Queue;
use feature 'say';

# Create a job queue and a flag for completion
my $jobs = Thread::Queue->new();
my $done = Thread::Queue->new();

# Here's the worker thread. It repeatedly receives from $jobs
# until it receives an undefined value, which signals that the
# queue is closed and all jobs have been processed.
threads->create(sub {
    while (defined(my $j = $jobs->dequeue())) {
        say "received job $j";
    }
    say "received all jobs";
    $done->enqueue(1);
});

# This sends 3 jobs to the worker over the $jobs queue
for my $j (1..3) {
    $jobs->enqueue($j);
    say "sent job $j";
}

# Signal that no more jobs will be sent
$jobs->end();
say "sent all jobs";

# We await the worker using the synchronization approach
$done->dequeue();

# Checking if the queue is empty
my $more_jobs = $jobs->pending();
say "received more jobs: ", $more_jobs ? "true" : "false";

# Wait for all threads to finish
$_->join for threads->list;

This Perl script demonstrates a pattern similar to closing channels in other languages. Here’s how it works:

  1. We create a $jobs queue to send work from the main thread to a worker thread.

  2. We also create a $done queue for the worker to signal when it’s finished.

  3. The worker thread is created with threads->create(). It continuously dequeues jobs from $jobs until it receives an undefined value, which signals that the queue is closed.

  4. In the main thread, we enqueue 3 jobs to the $jobs queue.

  5. After sending all jobs, we call $jobs->end() to signal that no more jobs will be sent. This is equivalent to closing a channel in other languages.

  6. We wait for the worker to finish by dequeuing from the $done queue.

  7. Finally, we check if there are any more jobs in the queue using $jobs->pending().

To run this program, save it as closing_queues.pl and execute it with:

$ perl closing_queues.pl
sent job 1
sent job 2
sent job 3
sent all jobs
received job 1
received job 2
received job 3
received all jobs
received more jobs: false

This example demonstrates how to simulate channel-like behavior in Perl using threads and queues. While Perl doesn’t have built-in constructs exactly like channels, this approach provides similar functionality for communicating between threads and signaling completion.