7 |
|
* Pat Fisher, Mike Judd. |
8 |
|
*/ |
9 |
|
|
10 |
< |
import junit.framework.*; |
10 |
> |
import static java.util.concurrent.TimeUnit.MILLISECONDS; |
11 |
> |
|
12 |
|
import java.util.concurrent.CountDownLatch; |
13 |
|
import java.util.concurrent.atomic.AtomicBoolean; |
14 |
|
import java.util.concurrent.locks.LockSupport; |
15 |
< |
import static java.util.concurrent.TimeUnit.MILLISECONDS; |
15 |
> |
|
16 |
> |
import junit.framework.Test; |
17 |
> |
import junit.framework.TestSuite; |
18 |
|
|
19 |
|
public class LockSupportTest extends JSR166TestCase { |
20 |
|
public static void main(String[] args) { |
21 |
< |
junit.textui.TestRunner.run(suite()); |
21 |
> |
main(suite(), args); |
22 |
|
} |
23 |
|
|
24 |
|
public static Test suite() { |
25 |
|
return new TestSuite(LockSupportTest.class); |
26 |
|
} |
27 |
|
|
28 |
+ |
static { |
29 |
+ |
// Reduce the risk of rare disastrous classloading in first call to |
30 |
+ |
// LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773 |
31 |
+ |
Class<?> ensureLoaded = LockSupport.class; |
32 |
+ |
} |
33 |
+ |
|
34 |
|
/** |
35 |
|
* Returns the blocker object used by tests in this file. |
36 |
|
* Any old object will do; we'll return a convenient one. |
44 |
|
void park() { |
45 |
|
LockSupport.park(); |
46 |
|
} |
47 |
< |
void park(long millis) { |
39 |
< |
throw new UnsupportedOperationException(); |
40 |
< |
} |
47 |
> |
Thread.State parkedState() { return Thread.State.WAITING; } |
48 |
|
}, |
49 |
|
parkUntil() { |
50 |
|
void park(long millis) { |
60 |
|
void park() { |
61 |
|
LockSupport.park(theBlocker()); |
62 |
|
} |
63 |
< |
void park(long millis) { |
57 |
< |
throw new UnsupportedOperationException(); |
58 |
< |
} |
63 |
> |
Thread.State parkedState() { return Thread.State.WAITING; } |
64 |
|
}, |
65 |
|
parkUntilBlocker() { |
66 |
|
void park(long millis) { |
75 |
|
}; |
76 |
|
|
77 |
|
void park() { park(2 * LONG_DELAY_MS); } |
78 |
< |
abstract void park(long millis); |
78 |
> |
void park(long millis) { |
79 |
> |
throw new UnsupportedOperationException(); |
80 |
> |
} |
81 |
> |
Thread.State parkedState() { return Thread.State.TIMED_WAITING; } |
82 |
|
|
83 |
|
/** Returns a deadline to use with parkUntil. */ |
84 |
|
long deadline(long millis) { |
185 |
|
Thread t = newStartedThread(new CheckedRunnable() { |
186 |
|
public void realRun() { |
187 |
|
pleaseInterrupt.countDown(); |
188 |
< |
do { |
188 |
> |
for (int tries = MAX_SPURIOUS_WAKEUPS; tries-->0; ) { |
189 |
|
parkMethod.park(); |
190 |
< |
// park may return spuriously |
191 |
< |
} while (! Thread.currentThread().isInterrupted()); |
190 |
> |
if (Thread.interrupted()) |
191 |
> |
return; |
192 |
> |
} |
193 |
> |
fail("too many consecutive spurious wakeups?"); |
194 |
|
}}); |
195 |
|
|
196 |
|
await(pleaseInterrupt); |
197 |
< |
assertThreadStaysAlive(t); |
197 |
> |
assertThreadBlocks(t, parkMethod.parkedState()); |
198 |
|
t.interrupt(); |
199 |
|
awaitTermination(t); |
200 |
|
} |
222 |
|
} |
223 |
|
public void testParkAfterInterrupt(final ParkMethod parkMethod) { |
224 |
|
final CountDownLatch pleaseInterrupt = new CountDownLatch(1); |
215 |
– |
final AtomicBoolean pleasePark = new AtomicBoolean(false); |
225 |
|
Thread t = newStartedThread(new CheckedRunnable() { |
226 |
|
public void realRun() throws Exception { |
227 |
|
pleaseInterrupt.countDown(); |
228 |
< |
while (!pleasePark.get()) |
228 |
> |
while (!Thread.currentThread().isInterrupted()) |
229 |
|
Thread.yield(); |
221 |
– |
assertTrue(Thread.currentThread().isInterrupted()); |
230 |
|
parkMethod.park(); |
231 |
< |
assertTrue(Thread.currentThread().isInterrupted()); |
231 |
> |
assertTrue(Thread.interrupted()); |
232 |
|
}}); |
233 |
|
|
234 |
|
await(pleaseInterrupt); |
235 |
|
t.interrupt(); |
228 |
– |
pleasePark.set(true); |
236 |
|
awaitTermination(t); |
237 |
|
} |
238 |
|
|
254 |
|
public void testParkTimesOut(final ParkMethod parkMethod) { |
255 |
|
Thread t = newStartedThread(new CheckedRunnable() { |
256 |
|
public void realRun() { |
257 |
< |
for (;;) { |
257 |
> |
for (int tries = MAX_SPURIOUS_WAKEUPS; tries-->0; ) { |
258 |
|
long startTime = System.nanoTime(); |
259 |
|
parkMethod.park(timeoutMillis()); |
253 |
– |
// park may return spuriously |
260 |
|
if (millisElapsedSince(startTime) >= timeoutMillis()) |
261 |
|
return; |
262 |
|
} |
263 |
+ |
fail("too many consecutive spurious wakeups?"); |
264 |
|
}}); |
265 |
|
|
266 |
|
awaitTermination(t); |
294 |
|
public void realRun() { |
295 |
|
Thread t = Thread.currentThread(); |
296 |
|
started.countDown(); |
297 |
< |
do { |
297 |
> |
for (int tries = MAX_SPURIOUS_WAKEUPS; tries-->0; ) { |
298 |
|
assertNull(LockSupport.getBlocker(t)); |
299 |
|
parkMethod.park(); |
300 |
|
assertNull(LockSupport.getBlocker(t)); |
301 |
< |
// park may return spuriously |
302 |
< |
} while (! Thread.currentThread().isInterrupted()); |
301 |
> |
if (Thread.interrupted()) |
302 |
> |
return; |
303 |
> |
} |
304 |
> |
fail("too many consecutive spurious wakeups?"); |
305 |
|
}}); |
306 |
|
|
307 |
|
long startTime = System.nanoTime(); |
317 |
|
assertNull(x); // ok |
318 |
|
if (millisElapsedSince(startTime) > LONG_DELAY_MS) |
319 |
|
fail("timed out"); |
320 |
+ |
if (t.getState() == Thread.State.TERMINATED) |
321 |
+ |
break; |
322 |
|
Thread.yield(); |
323 |
|
} |
324 |
|
} |