]> git.vpit.fr Git - perl/modules/Thread-Cleanup.git/blob - t/20-recurse.t
2e639623c1ab9dd67255bf1e160da4f0c091cc4b
[perl/modules/Thread-Cleanup.git] / t / 20-recurse.t
1 #!perl -T
2
3 use strict;
4 use warnings;
5
6 use Config qw/%Config/;
7
8 BEGIN {
9  if (!$Config{useithreads}) {
10   require Test::More;
11   Test::More->import;
12   plan(skip_all => 'This perl wasn\'t built to support threads');
13  }
14 }
15
16 use threads;
17 use threads::shared;
18
19 my ($num, $depth);
20 BEGIN {
21  $num   = 3;
22  $depth = 2;
23 }
24
25 use Test::More tests => (($num ** ($depth + 1) - 1) / ($num - 1) - 1 ) * (2 + 2) + 1;
26
27 use Thread::Cleanup;
28
29 diag "Using threads $threads::VERSION";
30 diag "Using threads::shared $threads::shared::VERSION";
31 diag 'This will leak some scalars';
32
33 our $x = -1;
34
35 my %ran    : shared;
36 my %nums   : shared;
37 my %called : shared;
38
39 my @tids;
40
41 sub spawn {
42  my ($num, $depth) = @_;
43  @tids = ();
44  return unless $depth > 0;
45  map {
46   local $x = $_;
47   my $thr = threads->create(\&cb, $_, $depth);
48   push @tids, $thr->tid;
49   $thr;
50  } 1 .. $num;
51 }
52
53 sub check {
54  lock %ran;
55  lock %called;
56  for (@tids) {
57   is $ran{$_},    1, "thread $_ was run once";
58   is $called{$_}, 1, "thread $_ destructor was called once";
59  }
60 }
61
62 sub cb {
63  my ($y, $depth) = @_;
64
65  my $tid = threads->tid;
66  {
67   lock %ran;
68   $ran{$tid}++;
69  }
70
71  {
72   lock %nums;
73   $nums{$tid} = $y;
74  }
75  is $x, $y, "\$x in thread $tid";
76  local $x = -$tid;
77
78  $_->join for spawn $num, $depth - 1;
79
80  check;
81 }
82
83 Thread::Cleanup::register {
84  my $tid = threads->tid;
85  {
86   lock %called;
87   $called{$tid}++;
88  }
89
90  my $num = do {
91   lock %nums;
92   $nums{$tid};
93  };
94
95  is $x, $num, "\$x in destructor of thread $tid";
96  local $x = $tid;
97 };
98
99 $_->join for spawn $num, $depth;
100
101 check;
102
103 is $x, -1, '$x in the main thread';
104