]> git.vpit.fr Git - perl/modules/Thread-Cleanup.git/blob - t/10-join.t
Test that the thread destructors are executed before global destruction
[perl/modules/Thread-Cleanup.git] / t / 10-join.t
1 #!perl -T
2
3 use strict;
4 use warnings;
5
6 use lib 't/lib';
7 use VPIT::TestHelpers;
8 use Thread::Cleanup::TestThreads;
9
10 use Test::More 'no_plan';
11
12 use Thread::Cleanup;
13
14 my %called : shared;
15 my $destr  : shared;
16 my %nums   : shared;
17
18 our $x = -1;
19
20 Thread::Cleanup::register {
21  my $tid = threads->tid;
22
23  {
24   lock %called;
25   $called{$tid}++;
26  }
27
28  my $num = do {
29   lock %nums;
30   $nums{$tid};
31  };
32  is $x, $num, "\$x in destructor of thread $tid";
33
34  my $gd = do {
35   lock $destr;
36   (defined $destr && $destr =~ /\[$tid\]/) ? 1 : undef;
37  };
38  is $gd, undef, "thread $tid destructor fires before global destruction";
39
40  local $x = $tid;
41 };
42
43 my %ran : shared;
44
45 sub cb {
46  my ($y) = @_;
47
48  my $tid = threads->tid;
49  {
50   lock %ran;
51   $ran{$tid}++;
52  }
53
54  my $immortal = VPIT::TestHelpers::Guard->new(sub {
55   # It seems we can't lock aggregates during global destruction, so we
56   # resort to using a string instead.
57   lock $destr;
58   $destr .= "[$tid]";
59  });
60  $immortal->{self} = $immortal;
61
62  {
63   lock %nums;
64   $nums{$tid} = $y;
65  }
66  is $x, $y, "\$x in thread $tid";
67  local $x = -$tid;
68 }
69
70
71 my @threads = map {
72  local $x = $_;
73  spawn(\&cb, $_);
74 } 0 .. 4;
75
76 my @tids = map $_->tid, @threads;
77
78 $_->join for @threads;
79
80 is $x, -1, '$x in the main thread';
81
82 for (@tids) {
83  is $ran{$_},    1, "thread $_ was run once";
84  is $called{$_}, 1, "thread $_ destructor was called once";
85 }