perl/dist/threads/t/free.t

215 lines
3.9 KiB
Perl

use strict;
use warnings;
BEGIN {
# Import test.pl into its own package
{
package Test;
require($ENV{PERL_CORE} ? '../../t/test.pl' : './t/test.pl');
}
use Config;
if (! $Config{'useithreads'}) {
Test::skip_all(q/Perl not compiled with 'useithreads'/);
}
}
use ExtUtils::testlib;
use threads;
BEGIN {
if (! eval 'use threads::shared; 1') {
Test::skip_all(q/threads::shared not available/);
}
require Thread::Queue;
$| = 1;
print("1..29\n"); ### Number of tests that will be run ###
}
Test::watchdog(120); # In case we get stuck
my $q = Thread::Queue->new();
my $TEST = 1;
sub ok
{
$q->enqueue(@_);
while ($q->pending()) {
my $ok = $q->dequeue();
my $name = $q->dequeue();
my $id = $TEST++;
if ($ok) {
print("ok $id - $name\n");
} else {
print("not ok $id - $name\n");
printf("# Failed test at line %d\n", (caller)[2]);
}
}
}
### Start of Testing ###
ok(1, 'Loaded');
# Tests freeing the Perl interpreter for each thread
# See http://www.nntp.perl.org/group/perl.perl5.porters/110772 for details
my ($COUNT, $STARTED) :shared;
sub threading_1 {
my $q = shift;
my $tid = threads->tid();
$q->enqueue($tid, "Thread $tid started");
my $id;
{
lock($STARTED);
$STARTED++;
$id = $STARTED;
}
if ($STARTED < 5) {
sleep(1);
threads->create('threading_1', $q)->detach();
}
if ($id == 1) {
sleep(2);
} elsif ($id == 2) {
sleep(6);
} elsif ($id == 3) {
sleep(3);
} elsif ($id == 4) {
sleep(1);
} else {
sleep(2);
}
lock($COUNT);
$COUNT++;
cond_signal($COUNT);
$q->enqueue($tid, "Thread $tid done");
}
{
$STARTED = 0;
$COUNT = 0;
threads->create('threading_1', $q)->detach();
{
my $cnt = 0;
while ($cnt < 5) {
{
lock($COUNT);
cond_wait($COUNT) if ($COUNT < 5);
$cnt = $COUNT;
}
threads->create(sub {
threads->create(sub { })->join();
})->join();
}
}
sleep(1);
}
ok($COUNT == 5, "Done - $COUNT threads");
sub threading_2 {
my $q = shift;
my $tid = threads->tid();
$q->enqueue($tid, "Thread $tid started");
{
lock($STARTED);
$STARTED++;
}
if ($STARTED < 5) {
threads->create('threading_2', $q)->detach();
}
threads->yield();
lock($COUNT);
$COUNT++;
cond_signal($COUNT);
$q->enqueue($tid, "Thread $tid done");
}
{
$STARTED = 0;
$COUNT = 0;
threads->create('threading_2', $q)->detach();
threads->create(sub {
threads->create(sub { })->join();
})->join();
{
lock($COUNT);
while ($COUNT < 5) {
cond_wait($COUNT);
}
}
sleep(1);
}
ok($COUNT == 5, "Done - $COUNT threads");
{
threads->create(sub { })->join();
}
ok(1, 'Join');
sub threading_3 {
my $q = shift;
my $tid = threads->tid();
$q->enqueue($tid, "Thread $tid started");
{
threads->create(sub {
my $q = shift;
my $tid = threads->tid();
$q->enqueue($tid, "Thread $tid started");
sleep(1);
lock($COUNT);
$COUNT++;
cond_signal($COUNT);
$q->enqueue($tid, "Thread $tid done");
}, $q)->detach();
}
lock($COUNT);
$COUNT++;
cond_signal($COUNT);
$q->enqueue($tid, "Thread $tid done");
}
{
$COUNT = 0;
threads->create(sub {
threads->create('threading_3', $q)->detach();
{
lock($COUNT);
while ($COUNT < 2) {
cond_wait($COUNT);
}
}
})->join();
sleep(1);
}
ok($COUNT == 2, "Done - $COUNT threads");
exit(0);
# EOF