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