ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/LockSupportTest.java
(Generate patch)

Comparing jsr166/src/test/tck/LockSupportTest.java (file contents):
Revision 1.12 by jsr166, Sat Nov 21 02:07:27 2009 UTC vs.
Revision 1.29 by jsr166, Fri May 12 18:48:11 2017 UTC

# Line 1 | Line 1
1   /*
2 < * Written by Doug Lea with assistance from members of JCP JSR-166
3 < * Expert Group and released to the public domain, as explained at
4 < * http://creativecommons.org/licenses/publicdomain
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 junit.framework.*;
11 < import java.util.*;
12 < import java.util.concurrent.*;
13 < import java.util.concurrent.locks.*;
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 <        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 <     * park is released by unpark occurring after park
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 <    public void testPark() throws InterruptedException {
39 <        Thread t = new Thread(new CheckedRunnable() {
40 <            public void realRun() {
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 <        t.start();
32 <        Thread.sleep(SHORT_DELAY_MS);
120 >        await(pleaseUnpark);
121          LockSupport.unpark(t);
122 <        t.join();
122 >        awaitTermination(t);
123      }
124  
125      /**
126 <     * park is released by unpark occurring before park
126 >     * park is released by preceding unpark
127       */
128 <    public void testPark2() throws InterruptedException {
129 <        Thread t = new Thread(new CheckedRunnable() {
130 <            public void realRun() throws InterruptedException {
131 <                Thread.sleep(SHORT_DELAY_MS);
132 <                LockSupport.park();
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 <        t.start();
157 >        await(pleaseUnpark);
158          LockSupport.unpark(t);
159 <        t.join();
159 >        pleasePark.set(true);
160 >        awaitTermination(t);
161      }
162  
163      /**
164 <     * park is released by interrupt
164 >     * park is released by subsequent interrupt
165       */
166 <    public void testPark3() throws InterruptedException {
167 <        Thread t = new Thread(new CheckedRunnable() {
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 <                LockSupport.park();
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 <        t.start();
198 <        Thread.sleep(SHORT_DELAY_MS);
197 >        await(pleaseInterrupt);
198 >        assertThreadStaysAlive(t);
199          t.interrupt();
200 <        t.join();
200 >        awaitTermination(t);
201      }
202  
203      /**
204 <     * park returns if interrupted before park
204 >     * park is released by preceding interrupt
205       */
206 <    public void testPark4() throws InterruptedException {
207 <        final ReentrantLock lock = new ReentrantLock();
208 <        lock.lock();
209 <        Thread t = new Thread(new CheckedRunnable() {
210 <            public void realRun() {
211 <                lock.lock();
212 <                LockSupport.park();
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 <        t.start();
237 >        await(pleaseInterrupt);
238          t.interrupt();
239 <        lock.unlock();
240 <        t.join();
239 >        pleasePark.set(true);
240 >        awaitTermination(t);
241      }
242  
243      /**
244 <     * parkNanos times out if not unparked
244 >     * timed park times out if not unparked
245       */
246 <    public void testParkNanos() throws InterruptedException {
247 <        Thread t = new Thread(new CheckedRunnable() {
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 <                LockSupport.parkNanos(1000);
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 <        t.start();
95 <        t.join();
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 <     * parkUntil times out if not unparked
284 >     * getBlocker returns the blocker object passed to park
285       */
286 <    public void testParkUntil() throws InterruptedException {
287 <        Thread t = new Thread(new CheckedRunnable() {
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 <                long d = new Date().getTime() + 100;
106 <                LockSupport.parkUntil(d);
377 >                parkMethod.park(Long.MIN_VALUE);
378              }});
379  
380 <        t.start();
110 <        t.join();
380 >        awaitTermination(t);
381      }
382   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines