1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. 7 * 8 * This code is distributed in the hope that it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11 * version 2 for more details (a copy is included in the LICENSE file that 12 * accompanied this code). 13 * 14 * You should have received a copy of the GNU General Public License version 15 * 2 along with this work; if not, write to the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 17 * 18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 19 * or visit www.oracle.com if you need additional information or have any 20 * questions. 21 */ 22 23 /* 24 * This file is available under and governed by the GNU General Public 25 * License version 2 only, as published by the Free Software Foundation. 26 * However, the following notice accompanied the original version of this 27 * file: 28 * 29 * Written by Martin Buchholz with assistance from members of JCP JSR-166 30 * Expert Group and released to the public domain, as explained at 31 * http://creativecommons.org/publicdomain/zero/1.0/ 32 */ 33 34 /* 35 * @test 36 * @library /test/lib 37 * @run main DoneTimedGetLoops 300 38 * @summary isDone returning true guarantees that subsequent timed get 39 * will never throw TimeoutException. 40 */ 41 42 import java.util.concurrent.ExecutionException; 43 import java.util.concurrent.FutureTask; 44 import java.util.concurrent.TimeUnit; 45 import java.util.concurrent.atomic.AtomicReference; 46 import jdk.test.lib.Utils; 47 48 @SuppressWarnings({"unchecked", "rawtypes", "deprecation"}) 49 public class DoneTimedGetLoops { 50 static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); 51 final long testDurationMillisDefault = 10_000L; 52 final long testDurationMillis; 53 54 static class PublicFutureTask extends FutureTask<Boolean> { 55 static final Runnable noop = new Runnable() { public void run() {} }; 56 PublicFutureTask() { super(noop, null); } 57 public void set(Boolean v) { super.set(v); } 58 public void setException(Throwable t) { super.setException(t); } 59 } 60 61 DoneTimedGetLoops(String[] args) { 62 testDurationMillis = (args.length > 0) ? 63 Long.valueOf(args[0]) : testDurationMillisDefault; 64 } 65 66 void test(String[] args) throws Throwable { 67 final long testDurationNanos = testDurationMillis * 1000L * 1000L; 68 final long quittingTimeNanos = System.nanoTime() + testDurationNanos; 69 70 final AtomicReference<PublicFutureTask> normalRef 71 = new AtomicReference<>(); 72 final AtomicReference<PublicFutureTask> abnormalRef 73 = new AtomicReference<>(); 74 75 final Throwable throwable = new Throwable(); 76 77 abstract class CheckedThread extends Thread { 78 CheckedThread(String name) { 79 super(name); 80 setDaemon(true); 81 start(); 82 } 83 /** Polls for quitting time. */ 84 protected boolean quittingTime() { 85 return System.nanoTime() - quittingTimeNanos > 0; 86 } 87 /** Polls occasionally for quitting time. */ 88 protected boolean quittingTime(long i) { 89 return (i % 1024) == 0 && quittingTime(); 90 } 91 protected abstract void realRun() throws Exception; 92 public void run() { 93 try { realRun(); } catch (Throwable t) { unexpected(t); } 94 } 95 } 96 97 Thread setter = new CheckedThread("setter") { 98 protected void realRun() { 99 while (! quittingTime()) { 100 PublicFutureTask future = new PublicFutureTask(); 101 normalRef.set(future); 102 future.set(Boolean.TRUE); 103 }}}; 104 105 Thread setterException = new CheckedThread("setterException") { 106 protected void realRun() { 107 while (! quittingTime()) { 108 PublicFutureTask future = new PublicFutureTask(); 109 abnormalRef.set(future); 110 future.setException(throwable); 111 }}}; 112 113 Thread doneTimedGetNormal = new CheckedThread("doneTimedGetNormal") { 114 protected void realRun() throws Exception { 115 while (! quittingTime()) { 116 PublicFutureTask future = normalRef.get(); 117 if (future != null) { 118 while (!future.isDone()) 119 ; 120 check(future.get(0L, TimeUnit.HOURS) == Boolean.TRUE); 121 }}}}; 122 123 Thread doneTimedGetAbnormal = new CheckedThread("doneTimedGetAbnormal") { 124 protected void realRun() throws Exception { 125 while (! quittingTime()) { 126 PublicFutureTask future = abnormalRef.get(); 127 if (future != null) { 128 while (!future.isDone()) 129 ; 130 try { future.get(0L, TimeUnit.HOURS); fail(); } 131 catch (ExecutionException t) { 132 check(t.getCause() == throwable); 133 } 134 }}}}; 135 136 for (Thread thread : new Thread[] { 137 setter, 138 setterException, 139 doneTimedGetNormal, 140 doneTimedGetAbnormal }) { 141 thread.join(LONG_DELAY_MS + testDurationMillis); 142 if (thread.isAlive()) { 143 System.err.printf("Hung thread: %s%n", thread.getName()); 144 failed++; 145 for (StackTraceElement e : thread.getStackTrace()) 146 System.err.println(e); 147 thread.join(LONG_DELAY_MS); 148 } 149 } 150 } 151 152 //--------------------- Infrastructure --------------------------- 153 volatile int passed = 0, failed = 0; 154 void pass() {passed++;} 155 void fail() {failed++; Thread.dumpStack();} 156 void fail(String msg) {System.err.println(msg); fail();} 157 void unexpected(Throwable t) {failed++; t.printStackTrace();} 158 void check(boolean cond) {if (cond) pass(); else fail();} 159 void equal(Object x, Object y) { 160 if (x == null ? y == null : x.equals(y)) pass(); 161 else fail(x + " not equal to " + y);} 162 public static void main(String[] args) throws Throwable { 163 new DoneTimedGetLoops(args).instanceMain(args);} 164 public void instanceMain(String[] args) throws Throwable { 165 try {test(args);} catch (Throwable t) {unexpected(t);} 166 System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); 167 if (failed > 0) throw new AssertionError("Some tests failed");} 168 }