Wakeup.java revision 11665:dbff4e4be178
1234353Sdim/* 2193323Sed * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved. 3193323Sed * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4193323Sed * 5193323Sed * This code is free software; you can redistribute it and/or modify it 6193323Sed * under the terms of the GNU General Public License version 2 only, as 7193323Sed * published by the Free Software Foundation. 8193323Sed * 9193323Sed * This code is distributed in the hope that it will be useful, but WITHOUT 10193323Sed * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11193323Sed * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12193323Sed * version 2 for more details (a copy is included in the LICENSE file that 13193323Sed * accompanied this code). 14193323Sed * 15193323Sed * You should have received a copy of the GNU General Public License version 16234353Sdim * 2 along with this work; if not, write to the Free Software Foundation, 17193323Sed * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18234353Sdim * 19239462Sdim * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20193323Sed * or visit www.oracle.com if you need additional information or have any 21193323Sed * questions. 22193323Sed */ 23239462Sdim 24193323Sed/* @test 25193323Sed * @bug 6405995 26193323Sed * @summary Unit test for selector wakeup and interruption 27193323Sed * @library .. 28193323Sed */ 29193323Sed 30218893Sdimimport java.io.*; 31193323Sedimport java.net.*; 32193323Sedimport java.nio.*; 33193323Sedimport java.nio.channels.*; 34193323Sedimport java.util.Random; 35193323Sed 36198090Srdivackypublic class Wakeup { 37198090Srdivacky 38193323Sed static void sleep(int millis) { 39193323Sed try { 40193323Sed Thread.sleep(millis); 41224145Sdim } catch (InterruptedException x) { 42224145Sdim x.printStackTrace(); 43224145Sdim } 44193323Sed } 45193323Sed 46221345Sdim static class Sleeper extends TestThread { 47193323Sed volatile boolean started = false; 48226633Sdim volatile int entries = 0; 49193323Sed volatile int wakeups = 0; 50198090Srdivacky volatile boolean wantInterrupt = false; 51193323Sed volatile boolean gotInterrupt = false; 52193323Sed volatile Exception exception = null; 53221345Sdim volatile boolean closed = false; 54193323Sed Object gate = new Object(); 55193323Sed 56193323Sed Selector sel; 57234353Sdim 58239462Sdim Sleeper(Selector sel) { 59234353Sdim super("Sleeper", System.err); 60234353Sdim this.sel = sel; 61234353Sdim } 62234353Sdim 63234353Sdim public void go() throws Exception { 64234353Sdim started = true; 65193323Sed for (;;) { 66234353Sdim synchronized (gate) { } 67239462Sdim entries++; 68234353Sdim try { 69193323Sed sel.select(); 70234353Sdim } catch (ClosedSelectorException x) { 71239462Sdim closed = true; 72193323Sed } 73234353Sdim boolean intr = Thread.currentThread().isInterrupted(); 74226633Sdim wakeups++; 75234353Sdim System.err.println("Wakeup " + wakeups 76226633Sdim + (closed ? " (closed)" : "") 77234353Sdim + (intr ? " (intr)" : "")); 78234353Sdim if (wakeups > 1000) 79226633Sdim throw new Exception("Too many wakeups"); 80239462Sdim if (closed) 81193323Sed return; 82193323Sed if (wantInterrupt) { 83193323Sed while (!Thread.interrupted()) 84218893Sdim Thread.yield(); 85234353Sdim gotInterrupt = true; 86239462Sdim wantInterrupt = false; 87226633Sdim } 88226633Sdim } 89234353Sdim } 90239462Sdim 91226633Sdim } 92226633Sdim 93193323Sed private static int checkedWakeups = 0; 94239462Sdim 95193323Sed private static void check(Sleeper sleeper, boolean intr) 96234353Sdim throws Exception 97234353Sdim { 98221345Sdim checkedWakeups++; 99226633Sdim if (sleeper.wakeups > checkedWakeups) { 100234353Sdim sleeper.finish(100); 101234353Sdim throw new Exception("Sleeper has run ahead"); 102226633Sdim } 103226633Sdim int n = 0; 104239462Sdim while (sleeper.wakeups < checkedWakeups) { 105239462Sdim sleep(50); 106226633Sdim if ((n += 50) > 1000) { 107239462Sdim sleeper.finish(100); 108226633Sdim throw new Exception("Sleeper appears to be dead (" 109239462Sdim + checkedWakeups + ")"); 110239462Sdim } 111226633Sdim } 112226633Sdim if (sleeper.wakeups > checkedWakeups) { 113239462Sdim sleeper.finish(100); 114239462Sdim throw new Exception("Too many wakeups: Expected " 115226633Sdim + checkedWakeups 116226633Sdim + ", got " + sleeper.wakeups); 117234353Sdim } 118239462Sdim if (intr) { 119239462Sdim n = 0; 120239462Sdim // Interrupts can sometimes be delayed, so wait 121239462Sdim while (!sleeper.gotInterrupt) { 122234353Sdim sleep(50); 123234353Sdim if ((n += 50) > 1000) { 124234353Sdim sleeper.finish(100); 125234353Sdim throw new Exception("Interrupt never delivered"); 126234353Sdim } 127234353Sdim } 128239462Sdim sleeper.gotInterrupt = false; 129239462Sdim } 130239462Sdim System.err.println("Check " + checkedWakeups 131239462Sdim + (intr ? " (intr " + n + ")" : "")); 132239462Sdim } 133239462Sdim 134193323Sed public static void main(String[] args) throws Exception { 135193323Sed 136193323Sed Selector sel = Selector.open(); 137234353Sdim 138234353Sdim // Wakeup before select 139234353Sdim sel.wakeup(); 140234353Sdim 141234353Sdim Sleeper sleeper = new Sleeper(sel); 142239462Sdim 143239462Sdim sleeper.start(); 144239462Sdim while (!sleeper.started) 145193323Sed sleep(50); 146193323Sed 147193323Sed check(sleeper, false); // 1 148193323Sed 149193323Sed for (int i = 2; i < 5; i++) { 150212904Sdim // Wakeup during select 151198090Srdivacky sel.wakeup(); 152212904Sdim check(sleeper, false); // 2 .. 4 153193323Sed } 154193323Sed 155193323Sed // Double wakeup 156193323Sed synchronized (sleeper.gate) { 157193323Sed sel.wakeup(); 158193323Sed check(sleeper, false); // 5 159221345Sdim sel.wakeup(); 160193323Sed sel.wakeup(); 161193323Sed } 162193323Sed check(sleeper, false); // 6 163198090Srdivacky 164198090Srdivacky // Interrupt 165193323Sed synchronized (sleeper.gate) { 166193323Sed sleeper.wantInterrupt = true; 167234353Sdim sleeper.interrupt(); 168234353Sdim check(sleeper, true); // 7 169193323Sed } 170198090Srdivacky 171198090Srdivacky // Interrupt before select 172198090Srdivacky while (sleeper.entries < 8) 173193323Sed Thread.yield(); 174239462Sdim synchronized (sleeper.gate) { 175193323Sed sel.wakeup(); 176193323Sed check(sleeper, false); // 8 177193323Sed sleeper.wantInterrupt = true; 178199481Srdivacky sleeper.interrupt(); 179218893Sdim sleep(50); 180234353Sdim } 181218893Sdim check(sleeper, true); // 9 182234353Sdim 183234353Sdim // Close during select 184193323Sed while (sleeper.entries < 10) 185193323Sed Thread.yield(); 186193323Sed synchronized (sleeper.gate) { 187193323Sed sel.close(); 188198090Srdivacky check(sleeper, false); // 10 189193323Sed } 190193323Sed 191193323Sed if (sleeper.finish(200) == 0) 192193323Sed throw new Exception("Test failed"); 193198090Srdivacky if (!sleeper.closed) 194193323Sed throw new Exception("Selector not closed"); 195 } 196 197} 198