|
7 | 7 | }
|
8 | 8 | }
|
9 | 9 |
|
10 |
| -plan(20); |
| 10 | +plan(24); |
11 | 11 |
|
12 | 12 | # 2 tests
|
13 | 13 | {
|
@@ -92,5 +92,83 @@ plan(20);
|
92 | 92 | ok($b == 42, 'Second child thread also ran');
|
93 | 93 | }
|
94 | 94 |
|
95 |
| -# XXXX: Tests for nqp::threadyield() -- not tested in Perl 6 spectests either |
| 95 | +# 2 tests |
| 96 | +# Parent-child case for threadyield() |
| 97 | +# This test intentionally does not use proper synchronization primitives, |
| 98 | +# so that threadyield can be tested independently of locks/condvars/etc. |
| 99 | +{ |
| 100 | + my @a; |
| 101 | + my $t := nqp::newthread({ |
| 102 | + nqp::threadyield() until @a; |
| 103 | + nqp::push(@a, '1'); |
| 104 | + nqp::threadyield(); |
| 105 | + nqp::push(@a, '2'); |
| 106 | + }, 0); |
| 107 | + |
| 108 | + # Make sure child thread is at least *runnable* (if not actually running) |
| 109 | + # before running parent thread's code. |
| 110 | + nqp::threadrun($t); |
| 111 | + |
| 112 | + { |
| 113 | + nqp::push(@a, 'a'); |
| 114 | + nqp::threadyield(); |
| 115 | + nqp::push(@a, 'b'); |
| 116 | + nqp::threadyield(); |
| 117 | + nqp::push(@a, 'c'); |
| 118 | + } |
| 119 | + |
| 120 | + nqp::threadjoin($t); |
| 121 | + |
| 122 | + ok(@a[0] eq 'a', |
| 123 | + 'Looped threadyield() can force parent thread to act first'); |
| 124 | + |
| 125 | + # XXXX: This test goes wrong on nqp-j, always giving a,b,c,1,2; |
| 126 | + # It appears the threadyield() ops get ignored. |
| 127 | + my $order := nqp::join(',', @a); |
| 128 | + my $ok := $order eq 'a,1,b,2,c'; |
| 129 | + ok($ok, 'threadyield() properly interleaved parent and child threads'); |
| 130 | + say("# execution order = $order (expected a,1,b,2,c)") if !$ok; |
| 131 | +} |
| 132 | + |
| 133 | +# 2 tests |
| 134 | +# Sibling child threads case for threadyield() |
| 135 | +# This test intentionally does not use proper synchronization primitives, |
| 136 | +# so that threadyield can be tested independently of locks/condvars/etc. |
| 137 | +{ |
| 138 | + my @a; |
| 139 | + my $t1 := nqp::newthread({ |
| 140 | + nqp::push(@a, 'a'); |
| 141 | + nqp::threadyield(); |
| 142 | + nqp::push(@a, 'b'); |
| 143 | + nqp::threadyield(); |
| 144 | + nqp::push(@a, 'c'); |
| 145 | + }, 0); |
| 146 | + my $t2 := nqp::newthread({ |
| 147 | + nqp::threadyield() until @a; |
| 148 | + nqp::push(@a, '1'); |
| 149 | + nqp::threadyield(); |
| 150 | + nqp::push(@a, '2'); |
| 151 | + }, 0); |
| 152 | + |
| 153 | + # Make sure $t2 is at least *runnable* (if not actually running) |
| 154 | + # before $t1 becomes runnable. |
| 155 | + nqp::threadrun($t2); |
| 156 | + nqp::threadrun($t1); |
| 157 | + |
| 158 | + # Join in either order should work here. |
| 159 | + nqp::threadjoin($t1); |
| 160 | + nqp::threadjoin($t2); |
| 161 | + |
| 162 | + ok(@a[0] eq 'a', |
| 163 | + 'Looped threadyield() can force other thread to act first'); |
| 164 | + |
| 165 | + # XXXX: This test is flaky on nqp-j, often giving a,1,2,b,c |
| 166 | + # or more rarely a,1,b,c,2; in either case, one of the |
| 167 | + # threadyield() ops get ignored. |
| 168 | + my $order := nqp::join(',', @a); |
| 169 | + my $ok := $order eq 'a,1,b,2,c'; |
| 170 | + ok($ok, 'threadyield() properly interleaved two child threads'); |
| 171 | + say("# execution order = $order (expected a,1,b,2,c)") if !$ok; |
| 172 | +} |
| 173 | + |
96 | 174 | # XXXX: Stress tests -- Perl 6 spectests starting at S17-lowlevel/thread.t:100
|
0 commit comments