src/java.base/share/classes/sun/nio/ch/SelectorImpl.java
changeset 47216 71c04702a3d5
parent 46094 0c23b05caf7d
child 49248 15a0e60c8b97
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/nio/ch/SelectorImpl.java	Tue Sep 12 19:03:39 2017 +0200
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.nio.ch;
+
+import java.io.IOException;
+import java.net.SocketException;
+import java.nio.channels.ClosedSelectorException;
+import java.nio.channels.IllegalSelectorException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.spi.AbstractSelectableChannel;
+import java.nio.channels.spi.AbstractSelector;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+
+/**
+ * Base Selector implementation class.
+ */
+
+public abstract class SelectorImpl
+    extends AbstractSelector
+{
+
+    // The set of keys with data ready for an operation
+    protected Set<SelectionKey> selectedKeys;
+
+    // The set of keys registered with this Selector
+    protected HashSet<SelectionKey> keys;
+
+    // Public views of the key sets
+    private Set<SelectionKey> publicKeys;             // Immutable
+    private Set<SelectionKey> publicSelectedKeys;     // Removal allowed, but not addition
+
+    protected SelectorImpl(SelectorProvider sp) {
+        super(sp);
+        keys = new HashSet<>();
+        selectedKeys = new HashSet<>();
+        publicKeys = Collections.unmodifiableSet(keys);
+        publicSelectedKeys = Util.ungrowableSet(selectedKeys);
+    }
+
+    public Set<SelectionKey> keys() {
+        if (!isOpen())
+            throw new ClosedSelectorException();
+        return publicKeys;
+    }
+
+    public Set<SelectionKey> selectedKeys() {
+        if (!isOpen())
+            throw new ClosedSelectorException();
+        return publicSelectedKeys;
+    }
+
+    protected abstract int doSelect(long timeout) throws IOException;
+
+    private int lockAndDoSelect(long timeout) throws IOException {
+        synchronized (this) {
+            if (!isOpen())
+                throw new ClosedSelectorException();
+            synchronized (publicKeys) {
+                synchronized (publicSelectedKeys) {
+                    return doSelect(timeout);
+                }
+            }
+        }
+    }
+
+    public int select(long timeout)
+        throws IOException
+    {
+        if (timeout < 0)
+            throw new IllegalArgumentException("Negative timeout");
+        return lockAndDoSelect((timeout == 0) ? -1 : timeout);
+    }
+
+    public int select() throws IOException {
+        return select(0);
+    }
+
+    public int selectNow() throws IOException {
+        return lockAndDoSelect(0);
+    }
+
+    public void implCloseSelector() throws IOException {
+        wakeup();
+        synchronized (this) {
+            synchronized (publicKeys) {
+                synchronized (publicSelectedKeys) {
+                    implClose();
+                }
+            }
+        }
+    }
+
+    protected abstract void implClose() throws IOException;
+
+    public void putEventOps(SelectionKeyImpl sk, int ops) { }
+
+    protected final SelectionKey register(AbstractSelectableChannel ch,
+                                          int ops,
+                                          Object attachment)
+    {
+        if (!(ch instanceof SelChImpl))
+            throw new IllegalSelectorException();
+        SelectionKeyImpl k = new SelectionKeyImpl((SelChImpl)ch, this);
+        k.attach(attachment);
+        synchronized (publicKeys) {
+            implRegister(k);
+        }
+        k.interestOps(ops);
+        return k;
+    }
+
+    protected abstract void implRegister(SelectionKeyImpl ski);
+
+    void processDeregisterQueue() throws IOException {
+        // Precondition: Synchronized on this, keys, and selectedKeys
+        Set<SelectionKey> cks = cancelledKeys();
+        synchronized (cks) {
+            if (!cks.isEmpty()) {
+                Iterator<SelectionKey> i = cks.iterator();
+                while (i.hasNext()) {
+                    SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
+                    try {
+                        implDereg(ski);
+                    } catch (SocketException se) {
+                        throw new IOException("Error deregistering key", se);
+                    } finally {
+                        i.remove();
+                    }
+                }
+            }
+        }
+    }
+
+    protected abstract void implDereg(SelectionKeyImpl ski) throws IOException;
+
+    public abstract Selector wakeup();
+
+}