#!/usr/bin/perl -w
use strict;
use Benchmark qw(cmpthese);
use threads;
######################################################################
package model;
sub new {
my $class = shift @_;
my $self = {};
$self->{_start_sem} = Thread::Semaphore->new(0);
$self->{_end_sem} = Thread::Semaphore->new(0);
bless $self, $class;
return $self;
}
sub run_ipc() {
my $self = shift @_;
$self->{_start_sem}->up();
$self->{_end_sem}->down();
$self->{_src_thr}->join();
$self->{_dest_thr}->join();
return;
}
1;
##############################
package model::queue;
use base 'model';
sub new {
my $class = shift @_;
my $self = $class->SUPER::new(@_);
bless $self, $class;
$self->{_send_count} = $_[0];
my $q = $self->{_q} = Thread::Queue->new;
$self->{_src_thr} = threads->create(sub {
$self->{_start_sem}->down();
my $send_count = $self->{_send_count};
for (my $i = 0; $i < $send_count; $i++) {
$q->enqueue([$i]);
}
$q->enqueue(undef);
});
$self->{_dest_thr} = threads->create(sub {
for (;;) {
my $i = $q->dequeue();
last if (!defined($i));
}
$self->{_end_sem}->up();
});
return $self;
}
use base 'model';
sub new {
my $class = shift @_;
my $self = $class->SUPER::new(@_);
bless $self, $class;
$self->{_send_count} = $_[0];
my $q = $self->{_q} = Thread::GoChannel->new;
$self->{_src_thr} = threads->create(sub {
$self->{_start_sem}->down();
my $send_count = $self->{_send_count};
for (my $i = 0; $i < $send_count; $i++) {
$q->send([$i]);
}
$q->close;
});
$self->{_dest_thr} = threads->create(sub {
for (;;) {
my $i = $q->receive();
last if not defined $i;
}
$self->{_end_sem}->up();
});
return $self;
}
package main;
my ($send_count, $repetitions) = (500, 100);
GetOptions(
'help|?' => sub { pod2usage(1); },
'man' => sub { pod2usage(-verbose => 2); },
'N|number_to_send=i' => \$send_count,
'R|repetitions=i' => \$repetitions) or pod2usage(2);
pod2usage("$0: no arguments, please.\n") if (@ARGV != 0);
cmpthese($repetitions, {
channel => sub { model::channel->new($send_count)->run_ipc },
queue => sub { model::queue->new($send_count)->run_ipc },
});