Select in Perl

This example demonstrates how to use Perl’s select function to wait on multiple I/O operations. Although Perl’s select is different from the Go version, we can achieve similar functionality using threads and shared variables.

use strict;
use warnings;
use threads;
use Thread::Queue;
use Time::HiRes qw(sleep);

# Create two queues for our channels
my $c1 = Thread::Queue->new();
my $c2 = Thread::Queue->new();

# Create two threads to simulate concurrent operations
threads->create(sub {
    sleep(1);
    $c1->enqueue("one");
});

threads->create(sub {
    sleep(2);
    $c2->enqueue("two");
});

# Wait for both values using select
for my $i (0..1) {
    my @ready = threads->list(threads::running);
    my ($rh, $wh, $eh);
    vec($rh, fileno(STDIN), 1) = 1;
    my $nfound = select($rh, $wh, $eh, 0.1);

    if ($c1->pending()) {
        my $msg1 = $c1->dequeue();
        print "received $msg1\n";
    } elsif ($c2->pending()) {
        my $msg2 = $c2->dequeue();
        print "received $msg2\n";
    }
}

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

This Perl script simulates the behavior of the original example:

  1. We use Thread::Queue to create two queues that act as our channels.

  2. Two threads are created to simulate concurrent operations. Each thread sleeps for a specific amount of time before enqueueing a value.

  3. In the main loop, we use Perl’s select function to wait for a short time. This allows us to check both queues without blocking indefinitely.

  4. We check if either queue has pending items and dequeue them if available.

  5. Finally, we wait for all threads to finish using join().

To run the script:

$ perl select_example.pl
received one
received two

Note that the total execution time will be approximately 2 seconds, as both sleep operations execute concurrently in separate threads.

While this Perl implementation doesn’t have the same elegant syntax as the Go version, it demonstrates a similar concept of waiting on multiple operations concurrently.