1 /* 2 * Copyright (c) 2000, 2018, 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.spi.AbstractSelectableChannel; 34 import java.nio.channels.spi.AbstractSelector; 35 import java.nio.channels.spi.SelectorProvider; 36 import java.util.Collections; 37 import java.util.HashSet; 38 import java.util.Iterator; 39 import java.util.Set; 40 41 42 /** 43 * Base Selector implementation class. 44 */ 45 46 public abstract class SelectorImpl 47 extends AbstractSelector 48 { 49 // The set of keys registered with this Selector 50 protected final HashSet<SelectionKey> keys; 51 52 // The set of keys with data ready for an operation 53 protected final Set<SelectionKey> selectedKeys; 54 55 // Public views of the key sets 56 private final Set<SelectionKey> publicKeys; // Immutable 57 private final Set<SelectionKey> publicSelectedKeys; // Removal allowed, but not addition 58 59 protected SelectorImpl(SelectorProvider sp) { 60 super(sp); 61 keys = new HashSet<>(); 62 selectedKeys = new HashSet<>(); 63 publicKeys = Collections.unmodifiableSet(keys); 64 publicSelectedKeys = Util.ungrowableSet(selectedKeys); 65 } 66 67 @Override 68 public final Set<SelectionKey> keys() { 69 if (!isOpen()) 70 throw new ClosedSelectorException(); 71 return publicKeys; 72 } 73 74 @Override 75 public final 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 @Override 96 public final int select(long timeout) 97 throws IOException 98 { 99 if (timeout < 0) 100 throw new IllegalArgumentException("Negative timeout"); 101 return lockAndDoSelect((timeout == 0) ? -1 : timeout); 102 } 103 104 @Override 105 public final int select() throws IOException { 106 return select(0); 107 } 108 109 @Override 110 public final int selectNow() throws IOException { 111 return lockAndDoSelect(0); 112 } 113 114 @Override 115 public final void implCloseSelector() throws IOException { 116 wakeup(); 117 synchronized (this) { 118 synchronized (publicKeys) { 119 synchronized (publicSelectedKeys) { 120 implClose(); 121 } 122 } 123 } 124 } 125 126 protected abstract void implClose() throws IOException; 127 128 public abstract void putEventOps(SelectionKeyImpl sk, int ops); 129 130 @Override 131 protected final SelectionKey register(AbstractSelectableChannel ch, 132 int ops, 133 Object attachment) 134 { 135 if (!(ch instanceof SelChImpl)) 136 throw new IllegalSelectorException(); 137 SelectionKeyImpl k = new SelectionKeyImpl((SelChImpl)ch, this); 138 k.attach(attachment); 139 synchronized (publicKeys) { 140 implRegister(k); 141 } 142 k.interestOps(ops); 143 return k; 144 } 145 146 protected abstract void implRegister(SelectionKeyImpl ski); 147 148 protected abstract void implDereg(SelectionKeyImpl ski) throws IOException; 149 150 protected final void processDeregisterQueue() throws IOException { 151 // Precondition: Synchronized on this, keys, and selectedKeys 152 Set<SelectionKey> cks = cancelledKeys(); 153 synchronized (cks) { 154 if (!cks.isEmpty()) { 155 Iterator<SelectionKey> i = cks.iterator(); 156 while (i.hasNext()) { 157 SelectionKeyImpl ski = (SelectionKeyImpl)i.next(); 158 try { 159 implDereg(ski); 160 } catch (SocketException se) { 161 throw new IOException("Error deregistering key", se); 162 } finally { 163 i.remove(); 164 } 165 } 166 } 167 } 168 } 169 }