1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
|
use strict;
use warnings;
BEGIN {
use Config;
if (! $Config{'useithreads'}) {
print("1..0 # SKIP Perl not compiled with 'useithreads'\n");
exit(0);
}
}
use threads;
use threads::shared;
use Thread::Queue;
BEGIN { # perl RT 133382
if ($] == 5.008) {
require 't/test.pl'; # Test::More work-alike for Perl 5.8.0
} else {
require Test::More;
}
Test::More->import();
} # end BEGIN
plan('tests' => 46);
# Regular array
my @ary1 = qw/foo bar baz/;
push(@ary1, [ 1..3 ], { 'qux' => 99 });
# Shared array
my @ary2 :shared = (99, 21, 86);
# Regular hash-based object
my $obj1 = {
'foo' => 'bar',
'qux' => 99,
'biff' => [ qw/fee fi fo/ ],
'boff' => { 'bork' => 'true' },
};
bless($obj1, 'Foo');
# Shared hash-based object
my $obj2 = &share({});
$$obj2{'bar'} = 86;
$$obj2{'key'} = 'foo';
bless($obj2, 'Bar');
# Scalar ref
my $sref1 = \do{ my $scalar = 'foo'; };
# Shared scalar ref object
my $sref2 = \do{ my $scalar = 69; };
share($sref2);
bless($sref2, 'Baz');
# Ref of ref
my $foo = [ 5, 'bork', { 'now' => 123 } ];
my $bar = \$foo;
my $baz = \$bar;
my $qux = \$baz;
is_deeply($$$$qux, $foo, 'Ref of ref');
# Circular refs
my $cir1;
$cir1 = \$cir1;
my $cir1s : shared;
$cir1s = \$cir1s;
my $cir2;
$cir2 = [ \$cir2, { 'ref' => \$cir2 } ];
my $cir3 :shared = &share({});
$cir3->{'self'} = \$cir3;
bless($cir3, 'Circular');
# Queue up items
my $q = Thread::Queue->new(\@ary1, \@ary2);
ok($q, 'New queue');
is($q->pending(), 2, 'Queue count');
$q->enqueue($obj1, $obj2);
is($q->pending(), 4, 'Queue count');
$q->enqueue($sref1, $sref2, $foo, $qux);
is($q->pending(), 8, 'Queue count');
$q->enqueue($cir1, $cir1s, $cir2, $cir3);
is($q->pending(), 12, 'Queue count');
# Process items in thread
threads->create(sub {
is($q->pending(), 12, 'Queue count in thread');
my $tary1 = $q->dequeue();
ok($tary1, 'Thread got item');
is(ref($tary1), 'ARRAY', 'Item is array ref');
is_deeply($tary1, \@ary1, 'Complex array');
$$tary1[1] = 123;
my $tary2 = $q->dequeue();
ok($tary2, 'Thread got item');
is(ref($tary2), 'ARRAY', 'Item is array ref');
for (my $ii=0; $ii < @ary2; $ii++) {
is($$tary2[$ii], $ary2[$ii], 'Shared array element check');
}
$$tary2[1] = 444;
my $tobj1 = $q->dequeue();
ok($tobj1, 'Thread got item');
is(ref($tobj1), 'Foo', 'Item is object');
is_deeply($tobj1, $obj1, 'Object comparison');
$$tobj1{'foo'} = '.|.';
$$tobj1{'smiley'} = ':)';
my $tobj2 = $q->dequeue();
ok($tobj2, 'Thread got item');
is(ref($tobj2), 'Bar', 'Item is object');
is($$tobj2{'bar'}, 86, 'Shared object element check');
is($$tobj2{'key'}, 'foo', 'Shared object element check');
$$tobj2{'tick'} = 'tock';
$$tobj2{'frowny'} = ':(';
my $tsref1 = $q->dequeue();
ok($tsref1, 'Thread got item');
is(ref($tsref1), 'SCALAR', 'Item is scalar ref');
is($$tsref1, 'foo', 'Scalar ref contents');
$$tsref1 = 0;
my $tsref2 = $q->dequeue();
ok($tsref2, 'Thread got item');
is(ref($tsref2), 'Baz', 'Item is object');
is($$tsref2, 69, 'Shared scalar ref contents');
$$tsref2 = 'zzz';
my $myfoo = $q->dequeue();
is_deeply($myfoo, $foo, 'Array ref');
my $qux = $q->dequeue();
is_deeply($$$$qux, $foo, 'Ref of ref');
my ($c1, $c1s, $c2, $c3) = $q->dequeue(4);
SKIP: {
skip("Needs threads::shared >= 1.19", 5)
if ($threads::shared::VERSION < 1.19);
is(threads::shared::_id($$c1),
threads::shared::_id($c1),
'Circular ref - scalar');
is(threads::shared::_id($$c1s),
threads::shared::_id($c1s),
'Circular ref - shared scalar');
is(threads::shared::_id(${$c2->[0]}),
threads::shared::_id($c2),
'Circular ref - array');
is(threads::shared::_id(${$c2->[1]->{'ref'}}),
threads::shared::_id($c2),
'Circular ref - mixed');
is(threads::shared::_id(${$c3->{'self'}}),
threads::shared::_id($c3),
'Circular ref - hash');
}
is($q->pending(), 0, 'Empty queue');
my $nothing = $q->dequeue_nb();
ok(! defined($nothing), 'Nothing on queue');
})->join();
# Check results of thread's activities
is($q->pending(), 0, 'Empty queue');
is($ary1[1], 'bar', 'Array unchanged');
is($ary2[1], 444, 'Shared array changed');
is($$obj1{'foo'}, 'bar', 'Object unchanged');
ok(! exists($$obj1{'smiley'}), 'Object unchanged');
is($$obj2{'tick'}, 'tock', 'Shared object changed');
is($$obj2{'frowny'}, ':(', 'Shared object changed');
is($$sref1, 'foo', 'Scalar ref unchanged');
is($$sref2, 'zzz', 'Shared scalar ref changed');
exit(0);
# EOF
|