1 /* 2 * Copyright (c) 2000, 2017, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.nio.ch; 27 28 import java.io.IOException; 29 import java.net.SocketException; 30 import java.nio.channels.ClosedSelectorException; 31 import java.nio.channels.IllegalSelectorException; 32 import java.nio.channels.SelectionKey; 33 import java.nio.channels.Selector; 34 import java.nio.channels.spi.AbstractSelectableChannel; 35 import java.nio.channels.spi.AbstractSelector; 36 import java.nio.channels.spi.SelectorProvider; 37 import java.util.Collections; 38 import java.util.HashSet; 39 import java.util.Iterator; 40 import java.util.Set; 41 42 43 /** 44 * Base Selector implementation class. 45 */ 46 47 public abstract class SelectorImpl 48 extends AbstractSelector 49 { 50 51 // The set of keys with data ready for an operation 52 protected Set<SelectionKey> selectedKeys; 53 54 // The set of keys registered with this Selector 55 protected HashSet<SelectionKey> keys; 56 57 // Public views of the key sets 58 private Set<SelectionKey> publicKeys; // Immutable 59 private Set<SelectionKey> publicSelectedKeys; // Removal allowed, but not addition 60 61 protected SelectorImpl(SelectorProvider sp) { 62 super(sp); 63 keys = new HashSet<>(); 64 selectedKeys = new HashSet<>(); 65 publicKeys = Collections.unmodifiableSet(keys); 66 publicSelectedKeys = Util.ungrowableSet(selectedKeys); 67 } 68 69 public Set<SelectionKey> keys() { 70 if (!isOpen()) 71 throw new ClosedSelectorException(); 72 return publicKeys; 73 } 74 75 public Set<SelectionKey> selectedKeys() { 76 if (!isOpen()) 77 throw new ClosedSelectorException(); 78 return publicSelectedKeys; 79 } 80 81 protected abstract int doSelect(long timeout) throws IOException; 82 83 private int lockAndDoSelect(long timeout) throws IOException { 84 synchronized (this) { 85 if (!isOpen()) 86 throw new ClosedSelectorException(); 87 synchronized (publicKeys) { 88 synchronized (publicSelectedKeys) { 89 return doSelect(timeout); 90 } 91 } 92 } 93 } 94 95 public int select(long timeout) 96 throws IOException 97 { 98 if (timeout < 0) 99 throw new IllegalArgumentException("Negative timeout"); 100 return lockAndDoSelect((timeout == 0) ? -1 : timeout); 101 } 102 103 public int select() throws IOException { 104 return select(0); 105 } 106 107 public int selectNow() throws IOException { 108 return lockAndDoSelect(0); 109 } 110 111 public void implCloseSelector() throws IOException { 112 wakeup(); 113 synchronized (this) { 114 synchronized (publicKeys) { 115 synchronized (publicSelectedKeys) { 116 implClose(); 117 } 118 } 119 } 120 } 121 122 protected abstract void implClose() throws IOException; 123 124 public void putEventOps(SelectionKeyImpl sk, int ops) { } 125 126 protected final SelectionKey register(AbstractSelectableChannel ch, 127 int ops, 128 Object attachment) 129 { 130 if (!(ch instanceof SelChImpl)) 131 throw new IllegalSelectorException(); 132 SelectionKeyImpl k = new SelectionKeyImpl((SelChImpl)ch, this); 133 k.attach(attachment); 134 synchronized (publicKeys) { 135 implRegister(k); 136 } 137 k.interestOps(ops); 138 return k; 139 } 140 141 protected abstract void implRegister(SelectionKeyImpl ski); 142 143 void processDeregisterQueue() throws IOException { 144 // Precondition: Synchronized on this, keys, and selectedKeys 145 Set<SelectionKey> cks = cancelledKeys(); 146 synchronized (cks) { 147 if (!cks.isEmpty()) { 148 Iterator<SelectionKey> i = cks.iterator(); 149 while (i.hasNext()) { 150 SelectionKeyImpl ski = (SelectionKeyImpl)i.next(); 151 try { 152 implDereg(ski); 153 } catch (SocketException se) { 154 throw new IOException("Error deregistering key", se); 155 } finally { 156 i.remove(); 157 } 158 } 159 } 160 } 161 } 162 163 protected abstract void implDereg(SelectionKeyImpl ski) throws IOException; 164 165 public abstract Selector wakeup(); 166 167 }