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