1 /* 2 * Copyright (c) 2011, 2015, 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 /* 27 * KQueueSelectorImpl.java 28 * Implementation of Selector using FreeBSD / Mac OS X kqueues 29 * Derived from Sun's DevPollSelectorImpl 30 */ 31 32 package sun.nio.ch; 33 34 import java.io.IOException; 35 import java.io.FileDescriptor; 36 import java.nio.channels.*; 37 import java.nio.channels.spi.*; 38 import java.util.*; 39 40 class KQueueSelectorImpl 41 extends SelectorImpl 42 { 43 // File descriptors used for interrupt 44 protected int fd0; 45 protected int fd1; 46 47 // The kqueue manipulator 48 KQueueArrayWrapper kqueueWrapper; 49 50 // Count of registered descriptors (including interrupt) 51 private int totalChannels; 52 53 // Map from a file descriptor to an entry containing the selection key 54 private HashMap<Integer,MapEntry> fdMap; 55 56 // True if this Selector has been closed 57 private boolean closed = false; 58 59 // Lock for interrupt triggering and clearing 60 private Object interruptLock = new Object(); 61 private boolean interruptTriggered = false; 62 63 // used by updateSelectedKeys to handle cases where the same file 64 // descriptor is polled by more than one filter 65 private long updateCount; 66 67 // Used to map file descriptors to a selection key and "update count" 68 // (see updateSelectedKeys for usage). 69 private static class MapEntry { 70 SelectionKeyImpl ski; 71 long updateCount; 72 MapEntry(SelectionKeyImpl ski) { 73 this.ski = ski; 74 } 75 } 76 77 /** 78 * Package private constructor called by factory method in 79 * the abstract superclass Selector. 80 */ 81 KQueueSelectorImpl(SelectorProvider sp) { 82 super(sp); 83 long fds = IOUtil.makePipe(false); 84 fd0 = (int)(fds >>> 32); 85 fd1 = (int)fds; 86 try { 87 kqueueWrapper = new KQueueArrayWrapper(); 88 kqueueWrapper.initInterrupt(fd0, fd1); 89 fdMap = new HashMap<>(); 90 totalChannels = 1; 182 } 183 } 184 return numKeysUpdated; 185 } 186 187 188 protected void implClose() throws IOException { 189 if (!closed) { 190 closed = true; 191 192 // prevent further wakeup 193 synchronized (interruptLock) { 194 interruptTriggered = true; 195 } 196 197 FileDispatcherImpl.closeIntFD(fd0); 198 FileDispatcherImpl.closeIntFD(fd1); 199 if (kqueueWrapper != null) { 200 kqueueWrapper.close(); 201 kqueueWrapper = null; 202 selectedKeys = null; 203 204 // Deregister channels 205 Iterator<SelectionKey> i = keys.iterator(); 206 while (i.hasNext()) { 207 SelectionKeyImpl ski = (SelectionKeyImpl)i.next(); 208 deregister(ski); 209 SelectableChannel selch = ski.channel(); 210 if (!selch.isOpen() && !selch.isRegistered()) 211 ((SelChImpl)selch).kill(); 212 i.remove(); 213 } 214 totalChannels = 0; 215 } 216 fd0 = -1; 217 fd1 = -1; 218 } 219 } 220 221 222 protected void implRegister(SelectionKeyImpl ski) { 223 if (closed) 224 throw new ClosedSelectorException(); 225 int fd = IOUtil.fdVal(ski.channel.getFD()); 226 fdMap.put(Integer.valueOf(fd), new MapEntry(ski)); 227 totalChannels++; 228 keys.add(ski); 229 } 230 231 232 protected void implDereg(SelectionKeyImpl ski) throws IOException { 233 int fd = ski.channel.getFDVal(); 234 fdMap.remove(Integer.valueOf(fd)); 235 kqueueWrapper.release(ski.channel); 236 totalChannels--; 237 keys.remove(ski); 238 selectedKeys.remove(ski); 239 deregister((AbstractSelectionKey)ski); 240 SelectableChannel selch = ski.channel(); 241 if (!selch.isOpen() && !selch.isRegistered()) 242 ((SelChImpl)selch).kill(); 243 } 244 245 246 public void putEventOps(SelectionKeyImpl ski, int ops) { 247 if (closed) 248 throw new ClosedSelectorException(); 249 kqueueWrapper.setInterest(ski.channel, ops); 250 } 251 252 253 public Selector wakeup() { 254 synchronized (interruptLock) { 255 if (!interruptTriggered) { 256 kqueueWrapper.interrupt(); 257 interruptTriggered = true; 258 } 259 } | 1 /* 2 * Copyright (c) 2011, 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 /* 27 * KQueueSelectorImpl.java 28 * Implementation of Selector using FreeBSD / Mac OS X kqueues 29 * Derived from Sun's DevPollSelectorImpl 30 */ 31 32 package sun.nio.ch; 33 34 import java.io.IOException; 35 import java.nio.channels.*; 36 import java.nio.channels.spi.*; 37 import java.util.*; 38 39 class KQueueSelectorImpl 40 extends SelectorImpl 41 { 42 // File descriptors used for interrupt 43 protected int fd0; 44 protected int fd1; 45 46 // The kqueue manipulator 47 KQueueArrayWrapper kqueueWrapper; 48 49 // Count of registered descriptors (including interrupt) 50 private int totalChannels; 51 52 // Map from a file descriptor to an entry containing the selection key 53 private final HashMap<Integer,MapEntry> fdMap; 54 55 // True if this Selector has been closed 56 private boolean closed = false; 57 58 // Lock for interrupt triggering and clearing 59 private final Object interruptLock = new Object(); 60 private boolean interruptTriggered = false; 61 62 // used by updateSelectedKeys to handle cases where the same file 63 // descriptor is polled by more than one filter 64 private long updateCount; 65 66 // Used to map file descriptors to a selection key and "update count" 67 // (see updateSelectedKeys for usage). 68 private static class MapEntry { 69 final SelectionKeyImpl ski; 70 long updateCount; 71 MapEntry(SelectionKeyImpl ski) { 72 this.ski = ski; 73 } 74 } 75 76 /** 77 * Package private constructor called by factory method in 78 * the abstract superclass Selector. 79 */ 80 KQueueSelectorImpl(SelectorProvider sp) { 81 super(sp); 82 long fds = IOUtil.makePipe(false); 83 fd0 = (int)(fds >>> 32); 84 fd1 = (int)fds; 85 try { 86 kqueueWrapper = new KQueueArrayWrapper(); 87 kqueueWrapper.initInterrupt(fd0, fd1); 88 fdMap = new HashMap<>(); 89 totalChannels = 1; 181 } 182 } 183 return numKeysUpdated; 184 } 185 186 187 protected void implClose() throws IOException { 188 if (!closed) { 189 closed = true; 190 191 // prevent further wakeup 192 synchronized (interruptLock) { 193 interruptTriggered = true; 194 } 195 196 FileDispatcherImpl.closeIntFD(fd0); 197 FileDispatcherImpl.closeIntFD(fd1); 198 if (kqueueWrapper != null) { 199 kqueueWrapper.close(); 200 kqueueWrapper = null; 201 selectedKeys.clear(); 202 203 // Deregister channels 204 Iterator<SelectionKey> i = keys.iterator(); 205 while (i.hasNext()) { 206 SelectionKeyImpl ski = (SelectionKeyImpl)i.next(); 207 deregister(ski); 208 SelectableChannel selch = ski.channel(); 209 if (!selch.isOpen() && !selch.isRegistered()) 210 ((SelChImpl)selch).kill(); 211 i.remove(); 212 } 213 totalChannels = 0; 214 } 215 fd0 = -1; 216 fd1 = -1; 217 } 218 } 219 220 221 protected void implRegister(SelectionKeyImpl ski) { 222 if (closed) 223 throw new ClosedSelectorException(); 224 int fd = IOUtil.fdVal(ski.channel.getFD()); 225 fdMap.put(Integer.valueOf(fd), new MapEntry(ski)); 226 totalChannels++; 227 keys.add(ski); 228 } 229 230 231 protected void implDereg(SelectionKeyImpl ski) throws IOException { 232 int fd = ski.channel.getFDVal(); 233 fdMap.remove(Integer.valueOf(fd)); 234 kqueueWrapper.release(ski.channel); 235 totalChannels--; 236 keys.remove(ski); 237 selectedKeys.remove(ski); 238 deregister(ski); 239 SelectableChannel selch = ski.channel(); 240 if (!selch.isOpen() && !selch.isRegistered()) 241 ((SelChImpl)selch).kill(); 242 } 243 244 245 public void putEventOps(SelectionKeyImpl ski, int ops) { 246 if (closed) 247 throw new ClosedSelectorException(); 248 kqueueWrapper.setInterest(ski.channel, ops); 249 } 250 251 252 public Selector wakeup() { 253 synchronized (interruptLock) { 254 if (!interruptTriggered) { 255 kqueueWrapper.interrupt(); 256 interruptTriggered = true; 257 } 258 } |