Wakeup.java revision 16176:d74aefde91da
1/*
2 * Copyright (c) 2001, 2016, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/* @test
25 * @bug 6405995
26 * @summary Unit test for selector wakeup and interruption
27 * @library .. /lib/testlibrary/
28 */
29
30import java.io.*;
31import java.net.*;
32import java.nio.*;
33import java.nio.channels.*;
34import java.util.concurrent.CyclicBarrier;
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        private static final long TIMEOUT = jdk.testlibrary.Utils.adjustTimeout(20_000);
48
49        // barrier is used to synchronize sleeper thread and checking
50        // thread which is the main thread: when go() get to the end,
51        // then start checking the sleeper's status.
52        private static CyclicBarrier barrier = new CyclicBarrier(2);
53        private static int wakeups = 0;
54        private static int waits = 0;
55
56        volatile boolean interruptBeforeSelect = false;
57        volatile boolean started = false;
58        volatile boolean wantInterrupt = false;
59        volatile boolean closed = false;
60        Object gate = new Object();
61
62        Selector sel;
63
64        Sleeper(Selector sel, boolean wantInterrupt, boolean interruptBeforeSelect) {
65            super("Sleeper", System.err);
66            this.sel = sel;
67            this.wantInterrupt = wantInterrupt;
68            this.interruptBeforeSelect = interruptBeforeSelect;
69        }
70
71        public void go() throws Exception {
72            started = true;
73            if (interruptBeforeSelect) {
74                synchronized (gate) { }
75            }
76            wakeups++;
77            System.err.println("Wakeup, selecting, " + wakeups);
78            try {
79                sel.select();
80            } catch (ClosedSelectorException x) {
81                closed = true;
82            }
83            boolean intr = Thread.currentThread().isInterrupted();
84            System.err.println("Wakeup " + wakeups
85                               + (closed ? " (closed)" : "")
86                               + (intr ? " (intr)" : ""));
87            if (closed)
88                return;
89            if (wantInterrupt) {
90                while (!Thread.interrupted())
91                    Thread.yield();
92            }
93            System.err.println("Wakeup, waiting, " + wakeups);
94            barrier.await();
95            System.err.println("Wakeup, wait successfully, " + wakeups);
96        }
97
98        void check(boolean close) throws Exception {
99            waits++;
100            System.err.println("waiting sleeper, " + waits);
101            if (!close) {
102                barrier.await();
103                System.err.println("wait barrier successfully, " + waits);
104            }
105            if (finish(TIMEOUT) == 0)
106                throw new Exception("Test failed");
107            if (this.closed != close)
108                throw new Exception("Selector was closed");
109        }
110
111        void check() throws Exception {
112            check(false);
113        }
114
115        static Sleeper createSleeper(Selector sel, boolean wantInterrupt,
116                boolean interruptBeforeSelect) throws Exception {
117            if (!wantInterrupt && interruptBeforeSelect) {
118                throw new RuntimeException("Wrong parameters!");
119            }
120
121            Sleeper sleeper = new Sleeper(sel, wantInterrupt, interruptBeforeSelect);
122
123            if (interruptBeforeSelect) {
124                synchronized(sleeper.gate) {
125                    sleeper.start();
126                    while (!sleeper.started)
127                        sleep(50);
128                    sleeper.interrupt();
129                }
130            } else {
131                sleeper.start();
132                while (!sleeper.started)
133                    sleep(50);
134                if (wantInterrupt) {
135                    sleep(50);
136                    sleeper.interrupt();
137                }
138            }
139            return sleeper;
140        }
141    }
142
143    static Sleeper newSleeper(Selector sel) throws Exception {
144        return Sleeper.createSleeper(sel, false, false);
145    }
146
147    static Sleeper newSleeperWantInterrupt(Selector sel) throws Exception {
148        return Sleeper.createSleeper(sel, true, false);
149    }
150
151    static Sleeper newSleeperWantInterruptBeforeSelect(Selector sel) throws Exception {
152        return Sleeper.createSleeper(sel, true, true);
153    }
154
155    public static void main(String[] args) throws Exception {
156
157        Selector sel = Selector.open();
158
159        // Wakeup before select
160        sel.wakeup();
161
162        Sleeper sleeper = newSleeper(sel); // 1
163        sleeper.check();
164
165        for (int i = 2; i < 5; i++) {
166            // Wakeup during select
167            sleeper = newSleeper(sel);
168            sel.wakeup();
169            sleeper.check();         // 2 .. 4
170        }
171
172        // Double wakeup
173        sel.wakeup();
174        sel.wakeup();
175        sleeper = newSleeper(sel);
176        sleeper.check();            // 5
177
178        // Interrupt
179        sleeper = newSleeperWantInterrupt(sel);
180        sleeper.check();            // 6
181
182        // Interrupt before select
183        sleeper = newSleeperWantInterruptBeforeSelect(sel);
184        sleeper.check();            // 7
185
186        // Close during select
187        sleeper = newSleeper(sel);
188        sel.close();
189        sleeper.check();           // 8
190
191        sleeper = newSleeper(sel);
192        sleeper.check(true);
193    }
194
195}
196