Wakeup.java revision 418:9a01bb6b5cc8
1/* 2 * Copyright 2001-2003 Sun Microsystems, Inc. All Rights Reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 20 * CA 95054 USA or visit www.sun.com if you need additional information or 21 * have any questions. 22 */ 23 24/* @test 25 * @bug 6405995 26 * @summary Unit test for selector wakeup and interruption 27 * @library .. 28 */ 29 30import java.io.*; 31import java.net.*; 32import java.nio.*; 33import java.nio.channels.*; 34import java.util.Random; 35 36public class Wakeup { 37 38 static void sleep(int millis) { 39 try { 40 Thread.sleep(millis); 41 } catch (InterruptedException x) { 42 x.printStackTrace(); 43 } 44 } 45 46 static class Sleeper extends TestThread { 47 volatile boolean started = false; 48 volatile int entries = 0; 49 volatile int wakeups = 0; 50 volatile boolean wantInterrupt = false; 51 volatile boolean gotInterrupt = false; 52 volatile Exception exception = null; 53 volatile boolean closed = false; 54 Object gate = new Object(); 55 56 Selector sel; 57 58 Sleeper(Selector sel) { 59 super("Sleeper", System.err); 60 this.sel = sel; 61 } 62 63 public void go() throws Exception { 64 started = true; 65 for (;;) { 66 synchronized (gate) { } 67 entries++; 68 try { 69 sel.select(); 70 } catch (ClosedSelectorException x) { 71 closed = true; 72 } 73 boolean intr = Thread.currentThread().isInterrupted(); 74 wakeups++; 75 System.err.println("Wakeup " + wakeups 76 + (closed ? " (closed)" : "") 77 + (intr ? " (intr)" : "")); 78 if (wakeups > 1000) 79 throw new Exception("Too many wakeups"); 80 if (closed) 81 return; 82 if (wantInterrupt) { 83 while (!Thread.interrupted()) 84 Thread.yield(); 85 gotInterrupt = true; 86 wantInterrupt = false; 87 } 88 } 89 } 90 91 } 92 93 private static int checkedWakeups = 0; 94 95 private static void check(Sleeper sleeper, boolean intr) 96 throws Exception 97 { 98 checkedWakeups++; 99 if (sleeper.wakeups > checkedWakeups) { 100 sleeper.finish(100); 101 throw new Exception("Sleeper has run ahead"); 102 } 103 int n = 0; 104 while (sleeper.wakeups < checkedWakeups) { 105 sleep(50); 106 if ((n += 50) > 1000) { 107 sleeper.finish(100); 108 throw new Exception("Sleeper appears to be dead (" 109 + checkedWakeups + ")"); 110 } 111 } 112 if (sleeper.wakeups > checkedWakeups) { 113 sleeper.finish(100); 114 throw new Exception("Too many wakeups: Expected " 115 + checkedWakeups 116 + ", got " + sleeper.wakeups); 117 } 118 if (intr) { 119 n = 0; 120 // Interrupts can sometimes be delayed, so wait 121 while (!sleeper.gotInterrupt) { 122 sleep(50); 123 if ((n += 50) > 1000) { 124 sleeper.finish(100); 125 throw new Exception("Interrupt never delivered"); 126 } 127 } 128 sleeper.gotInterrupt = false; 129 } 130 System.err.println("Check " + checkedWakeups 131 + (intr ? " (intr " + n + ")" : "")); 132 } 133 134 public static void main(String[] args) throws Exception { 135 136 Selector sel = Selector.open(); 137 138 // Wakeup before select 139 sel.wakeup(); 140 141 Sleeper sleeper = new Sleeper(sel); 142 143 sleeper.start(); 144 while (!sleeper.started) 145 sleep(50); 146 147 check(sleeper, false); // 1 148 149 for (int i = 2; i < 5; i++) { 150 // Wakeup during select 151 sel.wakeup(); 152 check(sleeper, false); // 2 .. 4 153 } 154 155 // Double wakeup 156 synchronized (sleeper.gate) { 157 sel.wakeup(); 158 check(sleeper, false); // 5 159 sel.wakeup(); 160 sel.wakeup(); 161 } 162 check(sleeper, false); // 6 163 164 // Interrupt 165 synchronized (sleeper.gate) { 166 sleeper.wantInterrupt = true; 167 sleeper.interrupt(); 168 check(sleeper, true); // 7 169 } 170 171 // Interrupt before select 172 while (sleeper.entries < 8) 173 Thread.yield(); 174 synchronized (sleeper.gate) { 175 sel.wakeup(); 176 check(sleeper, false); // 8 177 sleeper.wantInterrupt = true; 178 sleeper.interrupt(); 179 sleep(50); 180 } 181 check(sleeper, true); // 9 182 183 // Close during select 184 while (sleeper.entries < 10) 185 Thread.yield(); 186 synchronized (sleeper.gate) { 187 sel.close(); 188 check(sleeper, false); // 10 189 } 190 191 if (sleeper.finish(200) == 0) 192 throw new Exception("Test failed"); 193 if (!sleeper.closed) 194 throw new Exception("Selector not closed"); 195 } 196 197} 198