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