9 my ($module, $thread_safe_var);
11 $module = 'Scope::Upper';
12 $thread_safe_var = 'Scope::Upper::SU_THREADSAFE()';
19 if (defined &Scope::Upper::reap) {
20 &Scope::Upper::reap(sub { $var *= 2 });
34 # Keep the rest of the file untouched
39 if (defined $thread_safe_var) {
40 my $stat = run_perl "require POSIX; require $module; exit($thread_safe_var ? POSIX::EXIT_SUCCESS() : POSIX::EXIT_FAILURE())";
44 if ($res == POSIX::EXIT_SUCCESS()) {
46 } elsif ($res == POSIX::EXIT_FAILURE()) {
50 if (not defined $is_threadsafe) {
51 skip_all "Could not detect if $module is thread safe or not";
55 VPIT::TestHelpers->import(
56 threads => [ $module => $is_threadsafe ],
60 my $could_not_create_thread = 'Could not create thread';
62 use Test::Leaner tests => 1 + (2 + 2 * 2) + 6 + (2 * 4) + 2;
65 my ($affirmative, $desc) = @_;
67 my $res = load_test();
70 is $res, 1, "$desc: module loaded";
72 is $res, 0, "$desc: module not loaded";
78 my $code = eval "sub { require $module }";
83 is_loaded 0, 'main body, beginning';
85 # Test serial loadings
89 my $here = "first serial thread";
90 is_loaded 0, "$here, beginning";
93 is_loaded 1, "$here, after loading";
98 skip "$could_not_create_thread (serial 1)" => 2 unless defined $thr;
101 if (my $err = $thr->error) {
106 is_loaded 0, 'main body, in between serial loadings';
109 my $thr = spawn(sub {
110 my $here = "second serial thread";
111 is_loaded 0, "$here, beginning";
114 is_loaded 1, "$here, after loading";
119 skip "$could_not_create_thread (serial 2)" => 2 unless defined $thr;
122 if (my $err = $thr->error) {
127 is_loaded 0, 'main body, after serial loadings';
129 # Test nested loadings
132 my $thr = spawn(sub {
133 my $here = 'parent thread';
134 is_loaded 0, "$here, beginning";
137 my $kid = spawn(sub {
138 my $here = 'child thread';
139 is_loaded 0, "$here, beginning";
142 is_loaded 1, "$here, after loading";
147 skip "$could_not_create_thread (nested child)" => 2 unless defined $kid;
150 if (my $err = $kid->error) {
151 die "in child thread: $err\n";
155 is_loaded 0, "$here, after child terminated";
158 is_loaded 1, "$here, after loading";
163 skip "$could_not_create_thread (nested parent)" => (3 + 2) unless defined $thr;
166 if (my $err = $thr->error) {
171 is_loaded 0, 'main body, after nested loadings';
173 # Test parallel loadings
178 my @locks_down = (1) x 5;
179 my @locks_up = (0) x scalar @locks_down;
180 share($_) for @locks_down, @locks_up;
188 lock $locks_down[$id];
189 $locks_down[$id] = 0;
190 cond_broadcast $locks_down[$id];
195 cond_wait $locks_up[$id] until $locks_up[$id] == $peers;
203 lock $locks_down[$id];
204 cond_wait $locks_down[$id] until $locks_down[$id] == 0;
210 cond_signal $locks_up[$id];
215 my $thr1 = spawn(sub {
216 my $here = 'first simultaneous thread';
217 is_loaded 0, "$here, beginning";
221 is_loaded 1, "$here, after loading";
226 is_loaded 1, "$here, still loaded while also loaded in the other thread";
229 is_loaded 1, "$here, end";
234 skip "$could_not_create_thread (parallel 1)" => (4 * 2) unless defined $thr1;
236 my $thr2 = spawn(sub {
237 my $here = 'second simultaneous thread';
238 is_loaded 0, "$here, beginning";
242 is_loaded 0, "$here, loaded in other thread but not here";
246 is_loaded 1, "$here, after loading";
250 is_loaded 1, "$here, end";
255 sync_master($_) for 0 .. $#locks_down;
258 if (my $err = $thr1->error) {
262 skip "$could_not_create_thread (parallel 2)" => (4 * 1) unless defined $thr2;
265 if (my $err = $thr2->error) {
270 is_loaded 0, 'main body, after simultaneous threads';
273 is_loaded 1, 'main body, loaded at end';