blob: b3a8ed8374e4ba7eec1250472b5048179d6907ba [file] [log] [blame]
Calin Juravle8f0d92b2013-08-01 17:26:00 +01001/*
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
10package jsr166;
11
Narayan Kamath8e9a0e92015-04-28 11:40:00 +010012import static java.util.concurrent.TimeUnit.MILLISECONDS;
13
Calin Juravle8f0d92b2013-08-01 17:26:00 +010014import java.util.concurrent.CountDownLatch;
15import java.util.concurrent.atomic.AtomicBoolean;
16import java.util.concurrent.locks.LockSupport;
Narayan Kamath8e9a0e92015-04-28 11:40:00 +010017
18import junit.framework.Test;
19import junit.framework.TestSuite;
Calin Juravle8f0d92b2013-08-01 17:26:00 +010020
21public class LockSupportTest extends JSR166TestCase {
Narayan Kamath8e9a0e92015-04-28 11:40:00 +010022 // android-note: Removed because the CTS runner does a bad job of
23 // retrying tests that have suite() declarations.
24 //
25 // public static void main(String[] args) {
26 // main(suite(), args);
27 // }
28 // public static Test suite() {
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +000029 // return new TestSuite(LockSupportTest.class);
Narayan Kamath8e9a0e92015-04-28 11:40:00 +010030 // }
Calin Juravle8f0d92b2013-08-01 17:26:00 +010031
Przemyslaw Szczepaniakb8b75112016-03-11 15:59:10 +000032 static {
33 // Reduce the risk of rare disastrous classloading in first call to
34 // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
35 Class<?> ensureLoaded = LockSupport.class;
36 }
37
Calin Juravle8f0d92b2013-08-01 17:26:00 +010038 /**
39 * Returns the blocker object used by tests in this file.
40 * Any old object will do; we'll return a convenient one.
41 */
42 static Object theBlocker() {
43 return LockSupportTest.class;
44 }
45
46 enum ParkMethod {
47 park() {
48 void park() {
49 LockSupport.park();
50 }
51 void park(long millis) {
52 throw new UnsupportedOperationException();
53 }
54 },
55 parkUntil() {
56 void park(long millis) {
57 LockSupport.parkUntil(deadline(millis));
58 }
59 },
60 parkNanos() {
61 void park(long millis) {
62 LockSupport.parkNanos(MILLISECONDS.toNanos(millis));
63 }
64 },
65 parkBlocker() {
66 void park() {
67 LockSupport.park(theBlocker());
68 }
69 void park(long millis) {
70 throw new UnsupportedOperationException();
71 }
72 },
73 parkUntilBlocker() {
74 void park(long millis) {
75 LockSupport.parkUntil(theBlocker(), deadline(millis));
76 }
77 },
78 parkNanosBlocker() {
79 void park(long millis) {
80 LockSupport.parkNanos(theBlocker(),
81 MILLISECONDS.toNanos(millis));
82 }
83 };
84
85 void park() { park(2 * LONG_DELAY_MS); }
86 abstract void park(long millis);
87
88 /** Returns a deadline to use with parkUntil. */
89 long deadline(long millis) {
90 // beware of rounding
91 return System.currentTimeMillis() + millis + 1;
92 }
93 }
94
95 /**
96 * park is released by subsequent unpark
97 */
98 public void testParkBeforeUnpark_park() {
99 testParkBeforeUnpark(ParkMethod.park);
100 }
101 public void testParkBeforeUnpark_parkNanos() {
102 testParkBeforeUnpark(ParkMethod.parkNanos);
103 }
104 public void testParkBeforeUnpark_parkUntil() {
105 testParkBeforeUnpark(ParkMethod.parkUntil);
106 }
107 public void testParkBeforeUnpark_parkBlocker() {
108 testParkBeforeUnpark(ParkMethod.parkBlocker);
109 }
110 public void testParkBeforeUnpark_parkNanosBlocker() {
111 testParkBeforeUnpark(ParkMethod.parkNanosBlocker);
112 }
113 public void testParkBeforeUnpark_parkUntilBlocker() {
114 testParkBeforeUnpark(ParkMethod.parkUntilBlocker);
115 }
116 public void testParkBeforeUnpark(final ParkMethod parkMethod) {
117 final CountDownLatch pleaseUnpark = new CountDownLatch(1);
118 Thread t = newStartedThread(new CheckedRunnable() {
119 public void realRun() {
120 pleaseUnpark.countDown();
121 parkMethod.park();
122 }});
123
124 await(pleaseUnpark);
125 LockSupport.unpark(t);
126 awaitTermination(t);
127 }
128
129 /**
130 * park is released by preceding unpark
131 */
132 public void testParkAfterUnpark_park() {
133 testParkAfterUnpark(ParkMethod.park);
134 }
135 public void testParkAfterUnpark_parkNanos() {
136 testParkAfterUnpark(ParkMethod.parkNanos);
137 }
138 public void testParkAfterUnpark_parkUntil() {
139 testParkAfterUnpark(ParkMethod.parkUntil);
140 }
141 public void testParkAfterUnpark_parkBlocker() {
142 testParkAfterUnpark(ParkMethod.parkBlocker);
143 }
144 public void testParkAfterUnpark_parkNanosBlocker() {
145 testParkAfterUnpark(ParkMethod.parkNanosBlocker);
146 }
147 public void testParkAfterUnpark_parkUntilBlocker() {
148 testParkAfterUnpark(ParkMethod.parkUntilBlocker);
149 }
150 public void testParkAfterUnpark(final ParkMethod parkMethod) {
151 final CountDownLatch pleaseUnpark = new CountDownLatch(1);
152 final AtomicBoolean pleasePark = new AtomicBoolean(false);
153 Thread t = newStartedThread(new CheckedRunnable() {
154 public void realRun() {
155 pleaseUnpark.countDown();
156 while (!pleasePark.get())
157 Thread.yield();
158 parkMethod.park();
159 }});
160
161 await(pleaseUnpark);
162 LockSupport.unpark(t);
163 pleasePark.set(true);
164 awaitTermination(t);
165 }
166
167 /**
168 * park is released by subsequent interrupt
169 */
170 public void testParkBeforeInterrupt_park() {
171 testParkBeforeInterrupt(ParkMethod.park);
172 }
173 public void testParkBeforeInterrupt_parkNanos() {
174 testParkBeforeInterrupt(ParkMethod.parkNanos);
175 }
176 public void testParkBeforeInterrupt_parkUntil() {
177 testParkBeforeInterrupt(ParkMethod.parkUntil);
178 }
179 public void testParkBeforeInterrupt_parkBlocker() {
180 testParkBeforeInterrupt(ParkMethod.parkBlocker);
181 }
182 public void testParkBeforeInterrupt_parkNanosBlocker() {
183 testParkBeforeInterrupt(ParkMethod.parkNanosBlocker);
184 }
185 public void testParkBeforeInterrupt_parkUntilBlocker() {
186 testParkBeforeInterrupt(ParkMethod.parkUntilBlocker);
187 }
188 public void testParkBeforeInterrupt(final ParkMethod parkMethod) {
189 final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
190 Thread t = newStartedThread(new CheckedRunnable() {
191 public void realRun() {
192 pleaseInterrupt.countDown();
193 do {
194 parkMethod.park();
195 // park may return spuriously
196 } while (! Thread.currentThread().isInterrupted());
197 }});
198
199 await(pleaseInterrupt);
200 assertThreadStaysAlive(t);
201 t.interrupt();
202 awaitTermination(t);
203 }
204
205 /**
206 * park is released by preceding interrupt
207 */
208 public void testParkAfterInterrupt_park() {
209 testParkAfterInterrupt(ParkMethod.park);
210 }
211 public void testParkAfterInterrupt_parkNanos() {
212 testParkAfterInterrupt(ParkMethod.parkNanos);
213 }
214 public void testParkAfterInterrupt_parkUntil() {
215 testParkAfterInterrupt(ParkMethod.parkUntil);
216 }
217 public void testParkAfterInterrupt_parkBlocker() {
218 testParkAfterInterrupt(ParkMethod.parkBlocker);
219 }
220 public void testParkAfterInterrupt_parkNanosBlocker() {
221 testParkAfterInterrupt(ParkMethod.parkNanosBlocker);
222 }
223 public void testParkAfterInterrupt_parkUntilBlocker() {
224 testParkAfterInterrupt(ParkMethod.parkUntilBlocker);
225 }
226 public void testParkAfterInterrupt(final ParkMethod parkMethod) {
227 final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
228 final AtomicBoolean pleasePark = new AtomicBoolean(false);
229 Thread t = newStartedThread(new CheckedRunnable() {
230 public void realRun() throws Exception {
231 pleaseInterrupt.countDown();
232 while (!pleasePark.get())
233 Thread.yield();
234 assertTrue(Thread.currentThread().isInterrupted());
235 parkMethod.park();
236 assertTrue(Thread.currentThread().isInterrupted());
237 }});
238
239 await(pleaseInterrupt);
240 t.interrupt();
241 pleasePark.set(true);
242 awaitTermination(t);
243 }
244
245 /**
246 * timed park times out if not unparked
247 */
248 public void testParkTimesOut_parkNanos() {
249 testParkTimesOut(ParkMethod.parkNanos);
250 }
251 public void testParkTimesOut_parkUntil() {
252 testParkTimesOut(ParkMethod.parkUntil);
253 }
254 public void testParkTimesOut_parkNanosBlocker() {
255 testParkTimesOut(ParkMethod.parkNanosBlocker);
256 }
257 public void testParkTimesOut_parkUntilBlocker() {
258 testParkTimesOut(ParkMethod.parkUntilBlocker);
259 }
260 public void testParkTimesOut(final ParkMethod parkMethod) {
261 Thread t = newStartedThread(new CheckedRunnable() {
262 public void realRun() {
263 for (;;) {
264 long startTime = System.nanoTime();
265 parkMethod.park(timeoutMillis());
266 // park may return spuriously
267 if (millisElapsedSince(startTime) >= timeoutMillis())
268 return;
269 }
270 }});
271
272 awaitTermination(t);
273 }
274
275 /**
276 * getBlocker(null) throws NullPointerException
277 */
278 public void testGetBlockerNull() {
279 try {
280 LockSupport.getBlocker(null);
281 shouldThrow();
282 } catch (NullPointerException success) {}
283 }
284
285 /**
286 * getBlocker returns the blocker object passed to park
287 */
288 public void testGetBlocker_parkBlocker() {
289 testGetBlocker(ParkMethod.parkBlocker);
290 }
291 public void testGetBlocker_parkNanosBlocker() {
292 testGetBlocker(ParkMethod.parkNanosBlocker);
293 }
294 public void testGetBlocker_parkUntilBlocker() {
295 testGetBlocker(ParkMethod.parkUntilBlocker);
296 }
297 public void testGetBlocker(final ParkMethod parkMethod) {
298 final CountDownLatch started = new CountDownLatch(1);
299 Thread t = newStartedThread(new CheckedRunnable() {
300 public void realRun() {
301 Thread t = Thread.currentThread();
302 started.countDown();
303 do {
304 assertNull(LockSupport.getBlocker(t));
305 parkMethod.park();
306 assertNull(LockSupport.getBlocker(t));
307 // park may return spuriously
308 } while (! Thread.currentThread().isInterrupted());
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 Thread.yield();
325 }
326 }
327 }
328
329 /**
330 * timed park(0) returns immediately.
331 *
332 * Requires hotspot fix for:
333 * 6763959 java.util.concurrent.locks.LockSupport.parkUntil(0) blocks forever
334 * which is in jdk7-b118 and 6u25.
335 */
336 public void testPark0_parkNanos() {
337 testPark0(ParkMethod.parkNanos);
338 }
339 public void testPark0_parkUntil() {
340 testPark0(ParkMethod.parkUntil);
341 }
342 public void testPark0_parkNanosBlocker() {
343 testPark0(ParkMethod.parkNanosBlocker);
344 }
345 public void testPark0_parkUntilBlocker() {
346 testPark0(ParkMethod.parkUntilBlocker);
347 }
348 public void testPark0(final ParkMethod parkMethod) {
349 Thread t = newStartedThread(new CheckedRunnable() {
350 public void realRun() {
351 parkMethod.park(0L);
352 }});
353
354 awaitTermination(t);
355 }
356
357 /**
358 * timed park(Long.MIN_VALUE) returns immediately.
359 */
360 public void testParkNeg_parkNanos() {
361 testParkNeg(ParkMethod.parkNanos);
362 }
363 public void testParkNeg_parkUntil() {
364 testParkNeg(ParkMethod.parkUntil);
365 }
366 public void testParkNeg_parkNanosBlocker() {
367 testParkNeg(ParkMethod.parkNanosBlocker);
368 }
369 public void testParkNeg_parkUntilBlocker() {
370 testParkNeg(ParkMethod.parkUntilBlocker);
371 }
372 public void testParkNeg(final ParkMethod parkMethod) {
373 Thread t = newStartedThread(new CheckedRunnable() {
374 public void realRun() {
375 parkMethod.park(Long.MIN_VALUE);
376 }});
377
378 awaitTermination(t);
379 }
380}