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