Patch from Craig Berry to resolve test failures in VMS.
[p5sagit/p5-mst-13.2.git] / ext / threads / shared / t / cond.t
CommitLineData
13c1b207 1use warnings;
2
89661126 3BEGIN {
4 chdir 't' if -d 't';
b5135157 5 push @INC ,'../lib';
89661126 6 require Config; import Config;
7 unless ($Config{'useithreads'}) {
8 print "1..0 # Skip: no threads\n";
9 exit 0;
10 }
11}
cd055192 12$|++;
07e9638f 13print "1..31\n";
89661126 14use strict;
15
b5135157 16
89661126 17use threads;
18
19use threads::shared;
20
ab335022 21# We can't use the normal ok() type stuff here, as part of the test is
22# to check that the numbers get printed in the right order. Instead, we
23# set a 'base' number for each part of the test and specify the ok()
24# number as an offset from that base.
89661126 25
ab335022 26my $Base = 0;
27
28sub ok {
29 my ($offset, $bool, $text) = @_;
bb4e15c8 30 my $not = '';
31 $not = "not " unless $bool;
32 print "${not}ok " . ($Base + $offset) . " - $text\n";
89661126 33}
34
ab335022 35# test locking
36
37{
38 my $lock : shared;
39 my $tr;
40
41 # test that a subthread can't lock until parent thread has unlocked
42
43 {
44 lock($lock);
45 ok(1,1,"set first lock");
46 $tr = async {
47 lock($lock);
48 ok(3,1,"set lock in subthread");
49 };
50 threads->yield;
51 ok(2,1,"still got lock");
52 }
53 $tr->join;
54
55 $Base += 3;
56
57 # ditto with ref to thread
58
59 {
60 my $lockref = \$lock;
61 lock($lockref);
62 ok(1,1,"set first lockref");
63 $tr = async {
64 lock($lockref);
65 ok(3,1,"set lockref in subthread");
66 };
67 threads->yield;
68 ok(2,1,"still got lockref");
69 }
70 $tr->join;
71
72 $Base += 3;
73
74 # make sure recursive locks unlock at the right place
75 {
76 lock($lock);
77 ok(1,1,"set first recursive lock");
78 lock($lock);
79 threads->yield;
80 {
81 lock($lock);
82 threads->yield;
83 }
84 $tr = async {
85 lock($lock);
86 ok(3,1,"set recursive lock in subthread");
87 };
88 {
89 lock($lock);
90 threads->yield;
91 {
92 lock($lock);
93 threads->yield;
94 lock($lock);
95 threads->yield;
96 }
97 }
98 ok(2,1,"still got recursive lock");
99 }
100 $tr->join;
101
102 $Base += 3;
103
104 # Make sure a lock factory gives out fresh locks each time
105 # for both attribute and run-time shares
106
107 sub lock_factory1 { my $lock : shared; return \$lock; }
108 sub lock_factory2 { my $lock; share($lock); return \$lock; }
109
110 my (@locks1, @locks2);
111 push @locks1, lock_factory1() for 1..2;
112 push @locks1, lock_factory2() for 1..2;
113 push @locks2, lock_factory1() for 1..2;
114 push @locks2, lock_factory2() for 1..2;
115
116 ok(1,1,"lock factory: locking all locks");
117 lock $locks1[0];
118 lock $locks1[1];
119 lock $locks1[2];
120 lock $locks1[3];
121 ok(2,1,"lock factory: locked all locks");
122 $tr = async {
123 ok(3,1,"lock factory: child: locking all locks");
124 lock $locks2[0];
125 lock $locks2[1];
126 lock $locks2[2];
127 lock $locks2[3];
128 ok(4,1,"lock factory: child: locked all locks");
129 };
130 $tr->join;
131
132 $Base += 4;
89661126 133}
134
ab335022 135# test cond_signal()
136
137{
138 my $lock : shared;
139
140 sub foo {
141 lock($lock);
142 ok(1,1,"cond_signal: created first lock");
143 my $tr2 = threads->create(\&bar);
144 cond_wait($lock);
145 $tr2->join();
146 ok(5,1,"cond_signal: joined");
147 }
148
149 sub bar {
150 ok(2,1,"cond_signal: child before lock");
151 lock($lock);
152 ok(3,1,"cond_signal: child locked");
153 cond_signal($lock);
154 ok(4,1,"cond_signal: signalled");
155 }
156
157 my $tr = threads->create(\&foo);
158 $tr->join();
159
160 $Base += 5;
161
162 # ditto, but with lockrefs
163
164 my $lockref = \$lock;
165 sub foo2 {
166 lock($lockref);
167 ok(1,1,"cond_signal: ref: created first lock");
168 my $tr2 = threads->create(\&bar2);
169 cond_wait($lockref);
170 $tr2->join();
171 ok(5,1,"cond_signal: ref: joined");
172 }
173
174 sub bar2 {
175 ok(2,1,"cond_signal: ref: child before lock");
176 lock($lockref);
177 ok(3,1,"cond_signal: ref: child locked");
178 cond_signal($lockref);
179 ok(4,1,"cond_signal: ref: signalled");
180 }
181
182 $tr = threads->create(\&foo2);
183 $tr->join();
184
185 $Base += 5;
186
187}
188
189
190# test cond_broadcast()
191
192{
193 my $counter : shared = 0;
194
07e9638f 195 # broad(N) forks off broad(N-1) and goes into a wait, in such a way
196 # that it's guaranteed to reach the wait before its child enters the
197 # locked region. When N reaches 0, the child instead does a
198 # cond_broadcast to wake all its ancestors.
ab335022 199
07e9638f 200 sub broad {
201 my $n = shift;
202 my $th;
203 {
204 lock($counter);
205 if ($n > 0) {
206 $counter++;
207 $th = threads->new(\&broad, $n-1);
208 cond_wait($counter);
209 $counter += 10;
210 }
211 else {
212 ok(1, $counter == 3, "cond_broadcast: all three waiting");
213 cond_broadcast($counter);
214 }
215 }
216 $th->join if $th;
ab335022 217 }
07e9638f 218
219 threads->new(\&broad, 3)->join;
220 ok(2, $counter == 33, "cond_broadcast: all three threads woken");
ab335022 221 print "# counter=$counter\n";
222
07e9638f 223 $Base += 2;
ab335022 224
07e9638f 225
226 # ditto, but with refs and shared()
ab335022 227
502fc48e 228 my $counter2 = 0;
ab335022 229 share($counter2);
502fc48e 230 my $r = \$counter2;
ab335022 231
07e9638f 232 sub broad2 {
233 my $n = shift;
234 my $th;
235 {
236 lock($r);
237 if ($n > 0) {
238 $$r++;
239 $th = threads->new(\&broad2, $n-1);
240 cond_wait($r);
241 $$r += 10;
242 }
243 else {
244 ok(1, $$r == 3, "cond_broadcast: ref: all three waiting");
245 cond_broadcast($r);
246 }
247 }
248 $th->join if $th;
ab335022 249 }
250
07e9638f 251 threads->new(\&broad2, 3)->join;;
252 ok(2, $$r == 33, "cond_broadcast: ref: all three threads woken");
ab335022 253 print "# counter=$$r\n";
254
07e9638f 255 $Base += 2;
ab335022 256
257}
258
7b13eb73 259# test warnings;
260
261{
262 my $warncount = 0;
263 local $SIG{__WARN__} = sub { $warncount++ };
264
265 my $lock : shared;
266
267 cond_signal($lock);
268 ok(1, $warncount == 1, 'get warning on cond_signal');
269 cond_broadcast($lock);
270 ok(2, $warncount == 2, 'get warning on cond_broadcast');
271 no warnings 'threads';
272 cond_signal($lock);
273 ok(3, $warncount == 2, 'get no warning on cond_signal');
274 cond_broadcast($lock);
275 ok(4, $warncount == 2, 'get no warning on cond_broadcast');
276
277 $Base += 4;
278}
279
280
281