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