1 /* 2 * Copyright (c) 2001, 2013, 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.nio.channels.*; 30 import java.nio.channels.spi.*; 31 import java.util.*; 32 import sun.misc.*; 33 34 35 /** 36 * An abstract selector impl. 37 */ 38 39 abstract class AbstractPollSelectorImpl 40 extends SelectorImpl 41 { 42 43 // The poll fd array 44 PollArrayWrapper pollWrapper; 45 46 // Initial capacity of the pollfd array 47 protected final int INIT_CAP = 10; 48 49 // The list of SelectableChannels serviced by this Selector 50 protected SelectionKeyImpl[] channelArray; 51 52 // In some impls the first entry of channelArray is bogus 53 protected int channelOffset = 0; 54 55 // The number of valid channels in this Selector's poll array 56 protected int totalChannels; 57 58 // True if this Selector has been closed 59 private boolean closed = false; 60 61 // Lock for close and cleanup 62 private Object closeLock = new Object(); 63 AbstractPollSelectorImpl(SelectorProvider sp, int channels, int offset)64 AbstractPollSelectorImpl(SelectorProvider sp, int channels, int offset) { 65 super(sp); 66 this.totalChannels = channels; 67 this.channelOffset = offset; 68 } 69 putEventOps(SelectionKeyImpl sk, int ops)70 public void putEventOps(SelectionKeyImpl sk, int ops) { 71 synchronized (closeLock) { 72 if (closed) 73 throw new ClosedSelectorException(); 74 pollWrapper.putEventOps(sk.getIndex(), ops); 75 } 76 } 77 wakeup()78 public Selector wakeup() { 79 pollWrapper.interrupt(); 80 return this; 81 } 82 doSelect(long timeout)83 protected abstract int doSelect(long timeout) throws IOException; 84 implClose()85 protected void implClose() throws IOException { 86 synchronized (closeLock) { 87 if (closed) 88 return; 89 closed = true; 90 // Deregister channels 91 for(int i=channelOffset; i<totalChannels; i++) { 92 SelectionKeyImpl ski = channelArray[i]; 93 assert(ski.getIndex() != -1); 94 ski.setIndex(-1); 95 deregister(ski); 96 SelectableChannel selch = channelArray[i].channel(); 97 if (!selch.isOpen() && !selch.isRegistered()) 98 ((SelChImpl)selch).kill(); 99 } 100 implCloseInterrupt(); 101 pollWrapper.free(); 102 pollWrapper = null; 103 selectedKeys = null; 104 channelArray = null; 105 totalChannels = 0; 106 } 107 } 108 implCloseInterrupt()109 protected abstract void implCloseInterrupt() throws IOException; 110 111 /** 112 * Copy the information in the pollfd structs into the opss 113 * of the corresponding Channels. Add the ready keys to the 114 * ready queue. 115 */ updateSelectedKeys()116 protected int updateSelectedKeys() { 117 int numKeysUpdated = 0; 118 // Skip zeroth entry; it is for interrupts only 119 for (int i=channelOffset; i<totalChannels; i++) { 120 int rOps = pollWrapper.getReventOps(i); 121 if (rOps != 0) { 122 SelectionKeyImpl sk = channelArray[i]; 123 pollWrapper.putReventOps(i, 0); 124 if (selectedKeys.contains(sk)) { 125 if (sk.channel.translateAndSetReadyOps(rOps, sk)) { 126 numKeysUpdated++; 127 } 128 } else { 129 sk.channel.translateAndSetReadyOps(rOps, sk); 130 if ((sk.nioReadyOps() & sk.nioInterestOps()) != 0) { 131 selectedKeys.add(sk); 132 numKeysUpdated++; 133 } 134 } 135 } 136 } 137 return numKeysUpdated; 138 } 139 implRegister(SelectionKeyImpl ski)140 protected void implRegister(SelectionKeyImpl ski) { 141 synchronized (closeLock) { 142 if (closed) 143 throw new ClosedSelectorException(); 144 145 // Check to see if the array is large enough 146 if (channelArray.length == totalChannels) { 147 // Make a larger array 148 int newSize = pollWrapper.totalChannels * 2; 149 SelectionKeyImpl temp[] = new SelectionKeyImpl[newSize]; 150 // Copy over 151 for (int i=channelOffset; i<totalChannels; i++) 152 temp[i] = channelArray[i]; 153 channelArray = temp; 154 // Grow the NativeObject poll array 155 pollWrapper.grow(newSize); 156 } 157 channelArray[totalChannels] = ski; 158 ski.setIndex(totalChannels); 159 pollWrapper.addEntry(ski.channel); 160 totalChannels++; 161 keys.add(ski); 162 } 163 } 164 implDereg(SelectionKeyImpl ski)165 protected void implDereg(SelectionKeyImpl ski) throws IOException { 166 // Algorithm: Copy the sc from the end of the list and put it into 167 // the location of the sc to be removed (since order doesn't 168 // matter). Decrement the sc count. Update the index of the sc 169 // that is moved. 170 int i = ski.getIndex(); 171 assert (i >= 0); 172 if (i != totalChannels - 1) { 173 // Copy end one over it 174 SelectionKeyImpl endChannel = channelArray[totalChannels-1]; 175 channelArray[i] = endChannel; 176 endChannel.setIndex(i); 177 pollWrapper.release(i); 178 PollArrayWrapper.replaceEntry(pollWrapper, totalChannels - 1, 179 pollWrapper, i); 180 } else { 181 pollWrapper.release(i); 182 } 183 // Destroy the last one 184 channelArray[totalChannels-1] = null; 185 totalChannels--; 186 pollWrapper.totalChannels--; 187 ski.setIndex(-1); 188 // Remove the key from keys and selectedKeys 189 keys.remove(ski); 190 selectedKeys.remove(ski); 191 deregister((AbstractSelectionKey)ski); 192 SelectableChannel selch = ski.channel(); 193 if (!selch.isOpen() && !selch.isRegistered()) 194 ((SelChImpl)selch).kill(); 195 } 196 } 197