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.11 by jsr166, Tue Nov 17 12:46:10 2009 UTC vs.
Revision 1.31 by jsr166, Sat May 13 23:50:00 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);
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 +            Thread.State parkedState() { return Thread.State.WAITING; }
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 +            Thread.State parkedState() { return Thread.State.WAITING; }
64 +        },
65 +        parkUntilBlocker() {
66 +            void park(long millis) {
67 +                LockSupport.parkUntil(theBlocker(), deadline(millis));
68 +            }
69 +        },
70 +        parkNanosBlocker() {
71 +            void park(long millis) {
72 +                LockSupport.parkNanos(theBlocker(),
73 +                                      MILLISECONDS.toNanos(millis));
74 +            }
75 +        };
76 +
77 +        void park() { park(2 * LONG_DELAY_MS); }
78 +        void park(long millis) {
79 +            throw new UnsupportedOperationException();
80 +        }
81 +        Thread.State parkedState() { return Thread.State.TIMED_WAITING; }
82 +
83 +        /** Returns a deadline to use with parkUntil. */
84 +        long deadline(long millis) {
85 +            // beware of rounding
86 +            return System.currentTimeMillis() + millis + 1;
87 +        }
88 +    }
89 +
90 +    /**
91 +     * park is released by subsequent unpark
92 +     */
93 +    public void testParkBeforeUnpark_park() {
94 +        testParkBeforeUnpark(ParkMethod.park);
95 +    }
96 +    public void testParkBeforeUnpark_parkNanos() {
97 +        testParkBeforeUnpark(ParkMethod.parkNanos);
98 +    }
99 +    public void testParkBeforeUnpark_parkUntil() {
100 +        testParkBeforeUnpark(ParkMethod.parkUntil);
101 +    }
102 +    public void testParkBeforeUnpark_parkBlocker() {
103 +        testParkBeforeUnpark(ParkMethod.parkBlocker);
104 +    }
105 +    public void testParkBeforeUnpark_parkNanosBlocker() {
106 +        testParkBeforeUnpark(ParkMethod.parkNanosBlocker);
107 +    }
108 +    public void testParkBeforeUnpark_parkUntilBlocker() {
109 +        testParkBeforeUnpark(ParkMethod.parkUntilBlocker);
110 +    }
111 +    public void testParkBeforeUnpark(final ParkMethod parkMethod) {
112 +        final CountDownLatch pleaseUnpark = new CountDownLatch(1);
113 +        Thread t = newStartedThread(new CheckedRunnable() {
114 +            public void realRun() {
115 +                pleaseUnpark.countDown();
116 +                parkMethod.park();
117              }});
118  
119 <        t.start();
32 <        Thread.sleep(SHORT_DELAY_MS);
119 >        await(pleaseUnpark);
120          LockSupport.unpark(t);
121 <        t.join();
121 >        awaitTermination(t);
122      }
123  
124      /**
125 <     * park is released by unpark occurring before park
125 >     * park is released by preceding unpark
126       */
127 <    public void testPark2() throws InterruptedException {
128 <        Thread t = new Thread(new CheckedRunnable() {
129 <            public void realRun() throws InterruptedException {
130 <                Thread.sleep(SHORT_DELAY_MS);
131 <                LockSupport.park();
127 >    public void testParkAfterUnpark_park() {
128 >        testParkAfterUnpark(ParkMethod.park);
129 >    }
130 >    public void testParkAfterUnpark_parkNanos() {
131 >        testParkAfterUnpark(ParkMethod.parkNanos);
132 >    }
133 >    public void testParkAfterUnpark_parkUntil() {
134 >        testParkAfterUnpark(ParkMethod.parkUntil);
135 >    }
136 >    public void testParkAfterUnpark_parkBlocker() {
137 >        testParkAfterUnpark(ParkMethod.parkBlocker);
138 >    }
139 >    public void testParkAfterUnpark_parkNanosBlocker() {
140 >        testParkAfterUnpark(ParkMethod.parkNanosBlocker);
141 >    }
142 >    public void testParkAfterUnpark_parkUntilBlocker() {
143 >        testParkAfterUnpark(ParkMethod.parkUntilBlocker);
144 >    }
145 >    public void testParkAfterUnpark(final ParkMethod parkMethod) {
146 >        final CountDownLatch pleaseUnpark = new CountDownLatch(1);
147 >        final AtomicBoolean pleasePark = new AtomicBoolean(false);
148 >        Thread t = newStartedThread(new CheckedRunnable() {
149 >            public void realRun() {
150 >                pleaseUnpark.countDown();
151 >                while (!pleasePark.get())
152 >                    Thread.yield();
153 >                parkMethod.park();
154              }});
155  
156 <        t.start();
156 >        await(pleaseUnpark);
157          LockSupport.unpark(t);
158 <        t.join();
158 >        pleasePark.set(true);
159 >        awaitTermination(t);
160      }
161  
162      /**
163 <     * park is released by interrupt
163 >     * park is released by subsequent interrupt
164       */
165 <    public void testPark3() throws InterruptedException {
166 <        Thread t = new Thread(new CheckedRunnable() {
167 <            public void realRun() {
168 <                LockSupport.park();
165 >    public void testParkBeforeInterrupt_park() {
166 >        testParkBeforeInterrupt(ParkMethod.park);
167 >    }
168 >    public void testParkBeforeInterrupt_parkNanos() {
169 >        testParkBeforeInterrupt(ParkMethod.parkNanos);
170 >    }
171 >    public void testParkBeforeInterrupt_parkUntil() {
172 >        testParkBeforeInterrupt(ParkMethod.parkUntil);
173 >    }
174 >    public void testParkBeforeInterrupt_parkBlocker() {
175 >        testParkBeforeInterrupt(ParkMethod.parkBlocker);
176 >    }
177 >    public void testParkBeforeInterrupt_parkNanosBlocker() {
178 >        testParkBeforeInterrupt(ParkMethod.parkNanosBlocker);
179 >    }
180 >    public void testParkBeforeInterrupt_parkUntilBlocker() {
181 >        testParkBeforeInterrupt(ParkMethod.parkUntilBlocker);
182 >    }
183 >    public void testParkBeforeInterrupt(final ParkMethod parkMethod) {
184 >        final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
185 >        Thread t = newStartedThread(new CheckedRunnable() {
186 >            public void realRun() {
187 >                pleaseInterrupt.countDown();
188 >                for (int tries = MAX_SPURIOUS_WAKEUPS; tries-->0; ) {
189 >                    parkMethod.park();
190 >                    if (Thread.interrupted())
191 >                        return;
192 >                }
193 >                fail("too many consecutive spurious wakeups?");
194              }});
195  
196 <        t.start();
197 <        Thread.sleep(SHORT_DELAY_MS);
196 >        await(pleaseInterrupt);
197 >        assertThreadBlocks(t, parkMethod.parkedState());
198          t.interrupt();
199 <        t.join();
199 >        awaitTermination(t);
200      }
201  
202      /**
203 <     * park returns if interrupted before park
203 >     * park is released by preceding interrupt
204       */
205 <    public void testPark4() throws InterruptedException {
206 <        final ReentrantLock lock = new ReentrantLock();
207 <        lock.lock();
208 <        Thread t = new Thread(new CheckedRunnable() {
209 <            public void realRun() {
210 <                lock.lock();
211 <                LockSupport.park();
205 >    public void testParkAfterInterrupt_park() {
206 >        testParkAfterInterrupt(ParkMethod.park);
207 >    }
208 >    public void testParkAfterInterrupt_parkNanos() {
209 >        testParkAfterInterrupt(ParkMethod.parkNanos);
210 >    }
211 >    public void testParkAfterInterrupt_parkUntil() {
212 >        testParkAfterInterrupt(ParkMethod.parkUntil);
213 >    }
214 >    public void testParkAfterInterrupt_parkBlocker() {
215 >        testParkAfterInterrupt(ParkMethod.parkBlocker);
216 >    }
217 >    public void testParkAfterInterrupt_parkNanosBlocker() {
218 >        testParkAfterInterrupt(ParkMethod.parkNanosBlocker);
219 >    }
220 >    public void testParkAfterInterrupt_parkUntilBlocker() {
221 >        testParkAfterInterrupt(ParkMethod.parkUntilBlocker);
222 >    }
223 >    public void testParkAfterInterrupt(final ParkMethod parkMethod) {
224 >        final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
225 >        Thread t = newStartedThread(new CheckedRunnable() {
226 >            public void realRun() throws Exception {
227 >                pleaseInterrupt.countDown();
228 >                while (!Thread.currentThread().isInterrupted())
229 >                    Thread.yield();
230 >                parkMethod.park();
231 >                assertTrue(Thread.interrupted());
232              }});
233  
234 <        t.start();
234 >        await(pleaseInterrupt);
235          t.interrupt();
236 <        lock.unlock();
237 <        t.join();
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 (int tries = MAX_SPURIOUS_WAKEUPS; tries-->0; ) {
258 >                    long startTime = System.nanoTime();
259 >                    parkMethod.park(timeoutMillis());
260 >                    if (millisElapsedSince(startTime) >= timeoutMillis())
261 >                        return;
262 >                }
263 >                fail("too many consecutive spurious wakeups?");
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 <     * parkNanos times out if not unparked
280 >     * getBlocker returns the blocker object passed to park
281       */
282 <    public void testParkNanos() throws InterruptedException {
283 <        Thread t = new Thread(new CheckedRunnable() {
284 <            public void realRun() {
285 <                LockSupport.parkNanos(1000);
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 >                for (int tries = MAX_SPURIOUS_WAKEUPS; tries-->0; ) {
298 >                    assertNull(LockSupport.getBlocker(t));
299 >                    parkMethod.park();
300 >                    assertNull(LockSupport.getBlocker(t));
301 >                    if (Thread.interrupted())
302 >                        return;
303 >                }
304 >                fail("too many consecutive spurious wakeups?");
305              }});
306  
307 <        t.start();
308 <        t.join();
307 >        long startTime = System.nanoTime();
308 >        await(started);
309 >        for (;;) {
310 >            Object x = LockSupport.getBlocker(t);
311 >            if (x == theBlocker()) { // success
312 >                t.interrupt();
313 >                awaitTermination(t);
314 >                assertNull(LockSupport.getBlocker(t));
315 >                return;
316 >            } else {
317 >                assertNull(x);  // ok
318 >                if (millisElapsedSince(startTime) > LONG_DELAY_MS)
319 >                    fail("timed out");
320 >                if (t.getState() == Thread.State.TERMINATED)
321 >                    break;
322 >                Thread.yield();
323 >            }
324 >        }
325      }
326  
327 +    /**
328 +     * timed park(0) returns immediately.
329 +     *
330 +     * Requires hotspot fix for:
331 +     * 6763959 java.util.concurrent.locks.LockSupport.parkUntil(0) blocks forever
332 +     * which is in jdk7-b118 and 6u25.
333 +     */
334 +    public void testPark0_parkNanos() {
335 +        testPark0(ParkMethod.parkNanos);
336 +    }
337 +    public void testPark0_parkUntil() {
338 +        testPark0(ParkMethod.parkUntil);
339 +    }
340 +    public void testPark0_parkNanosBlocker() {
341 +        testPark0(ParkMethod.parkNanosBlocker);
342 +    }
343 +    public void testPark0_parkUntilBlocker() {
344 +        testPark0(ParkMethod.parkUntilBlocker);
345 +    }
346 +    public void testPark0(final ParkMethod parkMethod) {
347 +        Thread t = newStartedThread(new CheckedRunnable() {
348 +            public void realRun() {
349 +                parkMethod.park(0L);
350 +            }});
351 +
352 +        awaitTermination(t);
353 +    }
354  
355      /**
356 <     * parkUntil times out if not unparked
356 >     * timed park(Long.MIN_VALUE) returns immediately.
357       */
358 <    public void testParkUntil() throws InterruptedException {
359 <        Thread t = new Thread(new CheckedRunnable() {
360 <            public void realRun() {
361 <                long d = new Date().getTime() + 100;
362 <                LockSupport.parkUntil(d);
358 >    public void testParkNeg_parkNanos() {
359 >        testParkNeg(ParkMethod.parkNanos);
360 >    }
361 >    public void testParkNeg_parkUntil() {
362 >        testParkNeg(ParkMethod.parkUntil);
363 >    }
364 >    public void testParkNeg_parkNanosBlocker() {
365 >        testParkNeg(ParkMethod.parkNanosBlocker);
366 >    }
367 >    public void testParkNeg_parkUntilBlocker() {
368 >        testParkNeg(ParkMethod.parkUntilBlocker);
369 >    }
370 >    public void testParkNeg(final ParkMethod parkMethod) {
371 >        Thread t = newStartedThread(new CheckedRunnable() {
372 >            public void realRun() {
373 >                parkMethod.park(Long.MIN_VALUE);
374              }});
375  
376 <        t.start();
110 <        t.join();
376 >        awaitTermination(t);
377      }
378   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines