Skip to content

Commit 6071efa

Browse files
author
Geoffrey Broadwell
committed
Add parent-child and sibling-children tests for threadyield(). The interleaving threadyield() tests fail on both nqp-m and nqp-j, but this may be a case of intuitive semantics not matching true semantics.
1 parent 5bda620 commit 6071efa

File tree

2 files changed

+81
-3
lines changed

2 files changed

+81
-3
lines changed

t/concurrency/01-thread.t

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ BEGIN {
77
}
88
}
99

10-
plan(20);
10+
plan(24);
1111

1212
# 2 tests
1313
{
@@ -92,5 +92,83 @@ plan(20);
9292
ok($b == 42, 'Second child thread also ran');
9393
}
9494

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+
96174
# XXXX: Stress tests -- Perl 6 spectests starting at S17-lowlevel/thread.t:100

t/concurrency/TODO

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
** AsyncTask
44
** Uninstantiable
55
* nqp::op's:
6-
** Threads: threadyield
6+
** Threads: threadyield (current tests are flaky)
77
** ConcQueues: queuepoll
88
** Timers: timer
99
** Cancellations: cancel

0 commit comments

Comments
 (0)