ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/LockSupportTest.java
Revision: 1.29
Committed: Fri May 12 18:48:11 2017 UTC (7 years ago) by jsr166
Branch: MAIN
Changes since 1.28: +12 -7 lines
Log Message:
use MAX_SPURIOUS_WAKEUPS

File Contents

# Content
1 /*
2 * Written by Doug Lea and Martin Buchholz with assistance from
3 * members of JCP JSR-166 Expert Group and released to the public
4 * domain, as explained at
5 * http://creativecommons.org/publicdomain/zero/1.0/
6 * Other contributors include Andrew Wright, Jeffrey Hayes,
7 * Pat Fisher, Mike Judd.
8 */
9
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
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 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.
37 */
38 static Object theBlocker() {
39 return LockSupportTest.class;
40 }
41
42 enum ParkMethod {
43 park() {
44 void park() {
45 LockSupport.park();
46 }
47 void park(long millis) {
48 throw new UnsupportedOperationException();
49 }
50 },
51 parkUntil() {
52 void park(long millis) {
53 LockSupport.parkUntil(deadline(millis));
54 }
55 },
56 parkNanos() {
57 void park(long millis) {
58 LockSupport.parkNanos(MILLISECONDS.toNanos(millis));
59 }
60 },
61 parkBlocker() {
62 void park() {
63 LockSupport.park(theBlocker());
64 }
65 void park(long millis) {
66 throw new UnsupportedOperationException();
67 }
68 },
69 parkUntilBlocker() {
70 void park(long millis) {
71 LockSupport.parkUntil(theBlocker(), deadline(millis));
72 }
73 },
74 parkNanosBlocker() {
75 void park(long millis) {
76 LockSupport.parkNanos(theBlocker(),
77 MILLISECONDS.toNanos(millis));
78 }
79 };
80
81 void park() { park(2 * LONG_DELAY_MS); }
82 abstract void park(long millis);
83
84 /** Returns a deadline to use with parkUntil. */
85 long deadline(long millis) {
86 // beware of rounding
87 return System.currentTimeMillis() + millis + 1;
88 }
89 }
90
91 /**
92 * park is released by subsequent unpark
93 */
94 public void testParkBeforeUnpark_park() {
95 testParkBeforeUnpark(ParkMethod.park);
96 }
97 public void testParkBeforeUnpark_parkNanos() {
98 testParkBeforeUnpark(ParkMethod.parkNanos);
99 }
100 public void testParkBeforeUnpark_parkUntil() {
101 testParkBeforeUnpark(ParkMethod.parkUntil);
102 }
103 public void testParkBeforeUnpark_parkBlocker() {
104 testParkBeforeUnpark(ParkMethod.parkBlocker);
105 }
106 public void testParkBeforeUnpark_parkNanosBlocker() {
107 testParkBeforeUnpark(ParkMethod.parkNanosBlocker);
108 }
109 public void testParkBeforeUnpark_parkUntilBlocker() {
110 testParkBeforeUnpark(ParkMethod.parkUntilBlocker);
111 }
112 public void testParkBeforeUnpark(final ParkMethod parkMethod) {
113 final CountDownLatch pleaseUnpark = new CountDownLatch(1);
114 Thread t = newStartedThread(new CheckedRunnable() {
115 public void realRun() {
116 pleaseUnpark.countDown();
117 parkMethod.park();
118 }});
119
120 await(pleaseUnpark);
121 LockSupport.unpark(t);
122 awaitTermination(t);
123 }
124
125 /**
126 * park is released by preceding unpark
127 */
128 public void testParkAfterUnpark_park() {
129 testParkAfterUnpark(ParkMethod.park);
130 }
131 public void testParkAfterUnpark_parkNanos() {
132 testParkAfterUnpark(ParkMethod.parkNanos);
133 }
134 public void testParkAfterUnpark_parkUntil() {
135 testParkAfterUnpark(ParkMethod.parkUntil);
136 }
137 public void testParkAfterUnpark_parkBlocker() {
138 testParkAfterUnpark(ParkMethod.parkBlocker);
139 }
140 public void testParkAfterUnpark_parkNanosBlocker() {
141 testParkAfterUnpark(ParkMethod.parkNanosBlocker);
142 }
143 public void testParkAfterUnpark_parkUntilBlocker() {
144 testParkAfterUnpark(ParkMethod.parkUntilBlocker);
145 }
146 public void testParkAfterUnpark(final ParkMethod parkMethod) {
147 final CountDownLatch pleaseUnpark = new CountDownLatch(1);
148 final AtomicBoolean pleasePark = new AtomicBoolean(false);
149 Thread t = newStartedThread(new CheckedRunnable() {
150 public void realRun() {
151 pleaseUnpark.countDown();
152 while (!pleasePark.get())
153 Thread.yield();
154 parkMethod.park();
155 }});
156
157 await(pleaseUnpark);
158 LockSupport.unpark(t);
159 pleasePark.set(true);
160 awaitTermination(t);
161 }
162
163 /**
164 * park is released by subsequent interrupt
165 */
166 public void testParkBeforeInterrupt_park() {
167 testParkBeforeInterrupt(ParkMethod.park);
168 }
169 public void testParkBeforeInterrupt_parkNanos() {
170 testParkBeforeInterrupt(ParkMethod.parkNanos);
171 }
172 public void testParkBeforeInterrupt_parkUntil() {
173 testParkBeforeInterrupt(ParkMethod.parkUntil);
174 }
175 public void testParkBeforeInterrupt_parkBlocker() {
176 testParkBeforeInterrupt(ParkMethod.parkBlocker);
177 }
178 public void testParkBeforeInterrupt_parkNanosBlocker() {
179 testParkBeforeInterrupt(ParkMethod.parkNanosBlocker);
180 }
181 public void testParkBeforeInterrupt_parkUntilBlocker() {
182 testParkBeforeInterrupt(ParkMethod.parkUntilBlocker);
183 }
184 public void testParkBeforeInterrupt(final ParkMethod parkMethod) {
185 final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
186 Thread t = newStartedThread(new CheckedRunnable() {
187 public void realRun() {
188 pleaseInterrupt.countDown();
189 for (int tries = MAX_SPURIOUS_WAKEUPS; tries-->0; ) {
190 parkMethod.park();
191 if (Thread.interrupted())
192 return;
193 }
194 fail("too many consecutive spurious wakeups?");
195 }});
196
197 await(pleaseInterrupt);
198 assertThreadStaysAlive(t);
199 t.interrupt();
200 awaitTermination(t);
201 }
202
203 /**
204 * park is released by preceding interrupt
205 */
206 public void testParkAfterInterrupt_park() {
207 testParkAfterInterrupt(ParkMethod.park);
208 }
209 public void testParkAfterInterrupt_parkNanos() {
210 testParkAfterInterrupt(ParkMethod.parkNanos);
211 }
212 public void testParkAfterInterrupt_parkUntil() {
213 testParkAfterInterrupt(ParkMethod.parkUntil);
214 }
215 public void testParkAfterInterrupt_parkBlocker() {
216 testParkAfterInterrupt(ParkMethod.parkBlocker);
217 }
218 public void testParkAfterInterrupt_parkNanosBlocker() {
219 testParkAfterInterrupt(ParkMethod.parkNanosBlocker);
220 }
221 public void testParkAfterInterrupt_parkUntilBlocker() {
222 testParkAfterInterrupt(ParkMethod.parkUntilBlocker);
223 }
224 public void testParkAfterInterrupt(final ParkMethod parkMethod) {
225 final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
226 final AtomicBoolean pleasePark = new AtomicBoolean(false);
227 Thread t = newStartedThread(new CheckedRunnable() {
228 public void realRun() throws Exception {
229 pleaseInterrupt.countDown();
230 while (!pleasePark.get())
231 Thread.yield();
232 assertTrue(Thread.currentThread().isInterrupted());
233 parkMethod.park();
234 assertTrue(Thread.currentThread().isInterrupted());
235 }});
236
237 await(pleaseInterrupt);
238 t.interrupt();
239 pleasePark.set(true);
240 awaitTermination(t);
241 }
242
243 /**
244 * timed park times out if not unparked
245 */
246 public void testParkTimesOut_parkNanos() {
247 testParkTimesOut(ParkMethod.parkNanos);
248 }
249 public void testParkTimesOut_parkUntil() {
250 testParkTimesOut(ParkMethod.parkUntil);
251 }
252 public void testParkTimesOut_parkNanosBlocker() {
253 testParkTimesOut(ParkMethod.parkNanosBlocker);
254 }
255 public void testParkTimesOut_parkUntilBlocker() {
256 testParkTimesOut(ParkMethod.parkUntilBlocker);
257 }
258 public void testParkTimesOut(final ParkMethod parkMethod) {
259 Thread t = newStartedThread(new CheckedRunnable() {
260 public void realRun() {
261 for (int tries = MAX_SPURIOUS_WAKEUPS; tries-->0; ) {
262 long startTime = System.nanoTime();
263 parkMethod.park(timeoutMillis());
264 if (millisElapsedSince(startTime) >= timeoutMillis())
265 return;
266 }
267 fail("too many consecutive spurious wakeups?");
268 }});
269
270 awaitTermination(t);
271 }
272
273 /**
274 * getBlocker(null) throws NullPointerException
275 */
276 public void testGetBlockerNull() {
277 try {
278 LockSupport.getBlocker(null);
279 shouldThrow();
280 } catch (NullPointerException success) {}
281 }
282
283 /**
284 * getBlocker returns the blocker object passed to park
285 */
286 public void testGetBlocker_parkBlocker() {
287 testGetBlocker(ParkMethod.parkBlocker);
288 }
289 public void testGetBlocker_parkNanosBlocker() {
290 testGetBlocker(ParkMethod.parkNanosBlocker);
291 }
292 public void testGetBlocker_parkUntilBlocker() {
293 testGetBlocker(ParkMethod.parkUntilBlocker);
294 }
295 public void testGetBlocker(final ParkMethod parkMethod) {
296 final CountDownLatch started = new CountDownLatch(1);
297 Thread t = newStartedThread(new CheckedRunnable() {
298 public void realRun() {
299 Thread t = Thread.currentThread();
300 started.countDown();
301 for (int tries = MAX_SPURIOUS_WAKEUPS; tries-->0; ) {
302 assertNull(LockSupport.getBlocker(t));
303 parkMethod.park();
304 assertNull(LockSupport.getBlocker(t));
305 if (Thread.interrupted())
306 return;
307 }
308 fail("too many consecutive spurious wakeups?");
309 }});
310
311 long startTime = System.nanoTime();
312 await(started);
313 for (;;) {
314 Object x = LockSupport.getBlocker(t);
315 if (x == theBlocker()) { // success
316 t.interrupt();
317 awaitTermination(t);
318 assertNull(LockSupport.getBlocker(t));
319 return;
320 } else {
321 assertNull(x); // ok
322 if (millisElapsedSince(startTime) > LONG_DELAY_MS)
323 fail("timed out");
324 if (t.getState() == Thread.State.TERMINATED)
325 break;
326 Thread.yield();
327 }
328 }
329 }
330
331 /**
332 * timed park(0) returns immediately.
333 *
334 * Requires hotspot fix for:
335 * 6763959 java.util.concurrent.locks.LockSupport.parkUntil(0) blocks forever
336 * which is in jdk7-b118 and 6u25.
337 */
338 public void testPark0_parkNanos() {
339 testPark0(ParkMethod.parkNanos);
340 }
341 public void testPark0_parkUntil() {
342 testPark0(ParkMethod.parkUntil);
343 }
344 public void testPark0_parkNanosBlocker() {
345 testPark0(ParkMethod.parkNanosBlocker);
346 }
347 public void testPark0_parkUntilBlocker() {
348 testPark0(ParkMethod.parkUntilBlocker);
349 }
350 public void testPark0(final ParkMethod parkMethod) {
351 Thread t = newStartedThread(new CheckedRunnable() {
352 public void realRun() {
353 parkMethod.park(0L);
354 }});
355
356 awaitTermination(t);
357 }
358
359 /**
360 * timed park(Long.MIN_VALUE) returns immediately.
361 */
362 public void testParkNeg_parkNanos() {
363 testParkNeg(ParkMethod.parkNanos);
364 }
365 public void testParkNeg_parkUntil() {
366 testParkNeg(ParkMethod.parkUntil);
367 }
368 public void testParkNeg_parkNanosBlocker() {
369 testParkNeg(ParkMethod.parkNanosBlocker);
370 }
371 public void testParkNeg_parkUntilBlocker() {
372 testParkNeg(ParkMethod.parkUntilBlocker);
373 }
374 public void testParkNeg(final ParkMethod parkMethod) {
375 Thread t = newStartedThread(new CheckedRunnable() {
376 public void realRun() {
377 parkMethod.park(Long.MIN_VALUE);
378 }});
379
380 awaitTermination(t);
381 }
382 }