Home | History | Annotate | Download | only in ch
      1 /*
      2  * Copyright (c) 2001, 2010, 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 implementation of Selector for Solaris.
     37  */
     38 class DevPollSelectorImpl
     39     extends SelectorImpl
     40 {
     41 
     42     // File descriptors used for interrupt
     43     protected int fd0;
     44     protected int fd1;
     45 
     46     // The poll object
     47     DevPollArrayWrapper pollWrapper;
     48 
     49     // Maps from file descriptors to keys
     50     private Map<Integer,SelectionKeyImpl> fdToKey;
     51 
     52     // True if this Selector has been closed
     53     private boolean closed = false;
     54 
     55     // Lock for close/cleanup
     56     private Object closeLock = new Object();
     57 
     58     // Lock for interrupt triggering and clearing
     59     private Object interruptLock = new Object();
     60     private boolean interruptTriggered = false;
     61 
     62     /**
     63      * Package private constructor called by factory method in
     64      * the abstract superclass Selector.
     65      */
     66     DevPollSelectorImpl(SelectorProvider sp) {
     67         super(sp);
     68         long pipeFds = IOUtil.makePipe(false);
     69         fd0 = (int) (pipeFds >>> 32);
     70         fd1 = (int) pipeFds;
     71         pollWrapper = new DevPollArrayWrapper();
     72         pollWrapper.initInterrupt(fd0, fd1);
     73         fdToKey = new HashMap<Integer,SelectionKeyImpl>();
     74     }
     75 
     76     protected int doSelect(long timeout)
     77         throws IOException
     78     {
     79         if (closed)
     80             throw new ClosedSelectorException();
     81         processDeregisterQueue();
     82         try {
     83             begin();
     84             pollWrapper.poll(timeout);
     85         } finally {
     86             end();
     87         }
     88         processDeregisterQueue();
     89         int numKeysUpdated = updateSelectedKeys();
     90         if (pollWrapper.interrupted()) {
     91             // Clear the wakeup pipe
     92             pollWrapper.putReventOps(pollWrapper.interruptedIndex(), 0);
     93             synchronized (interruptLock) {
     94                 pollWrapper.clearInterrupted();
     95                 IOUtil.drain(fd0);
     96                 interruptTriggered = false;
     97             }
     98         }
     99         return numKeysUpdated;
    100     }
    101 
    102     /**
    103      * Update the keys whose fd's have been selected by the devpoll
    104      * driver. Add the ready keys to the ready queue.
    105      */
    106     private int updateSelectedKeys() {
    107         int entries = pollWrapper.updated;
    108         int numKeysUpdated = 0;
    109         for (int i=0; i<entries; i++) {
    110             int nextFD = pollWrapper.getDescriptor(i);
    111             SelectionKeyImpl ski = fdToKey.get(Integer.valueOf(nextFD));
    112             // ski is null in the case of an interrupt
    113             if (ski != null) {
    114                 int rOps = pollWrapper.getReventOps(i);
    115                 if (selectedKeys.contains(ski)) {
    116                     if (ski.channel.translateAndSetReadyOps(rOps, ski)) {
    117                         numKeysUpdated++;
    118                     }
    119                 } else {
    120                     ski.channel.translateAndSetReadyOps(rOps, ski);
    121                     if ((ski.nioReadyOps() & ski.nioInterestOps()) != 0) {
    122                         selectedKeys.add(ski);
    123                         numKeysUpdated++;
    124                     }
    125                 }
    126             }
    127         }
    128         return numKeysUpdated;
    129     }
    130 
    131     protected void implClose() throws IOException {
    132         if (closed)
    133             return;
    134         closed = true;
    135 
    136         // prevent further wakeup
    137         synchronized (interruptLock) {
    138             interruptTriggered = true;
    139         }
    140 
    141         FileDispatcherImpl.closeIntFD(fd0);
    142         FileDispatcherImpl.closeIntFD(fd1);
    143 
    144         pollWrapper.release(fd0);
    145         pollWrapper.closeDevPollFD();
    146         selectedKeys = null;
    147 
    148         // Deregister channels
    149         Iterator<SelectionKey> i = keys.iterator();
    150         while (i.hasNext()) {
    151             SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
    152             deregister(ski);
    153             SelectableChannel selch = ski.channel();
    154             if (!selch.isOpen() && !selch.isRegistered())
    155                 ((SelChImpl)selch).kill();
    156             i.remove();
    157         }
    158         fd0 = -1;
    159         fd1 = -1;
    160     }
    161 
    162     protected void implRegister(SelectionKeyImpl ski) {
    163         int fd = IOUtil.fdVal(ski.channel.getFD());
    164         fdToKey.put(Integer.valueOf(fd), ski);
    165         keys.add(ski);
    166     }
    167 
    168     protected void implDereg(SelectionKeyImpl ski) throws IOException {
    169         int i = ski.getIndex();
    170         assert (i >= 0);
    171         int fd = ski.channel.getFDVal();
    172         fdToKey.remove(Integer.valueOf(fd));
    173         pollWrapper.release(fd);
    174         ski.setIndex(-1);
    175         keys.remove(ski);
    176         selectedKeys.remove(ski);
    177         deregister((AbstractSelectionKey)ski);
    178         SelectableChannel selch = ski.channel();
    179         if (!selch.isOpen() && !selch.isRegistered())
    180             ((SelChImpl)selch).kill();
    181     }
    182 
    183     void putEventOps(SelectionKeyImpl sk, int ops) {
    184         if (closed)
    185             throw new ClosedSelectorException();
    186         int fd = IOUtil.fdVal(sk.channel.getFD());
    187         pollWrapper.setInterest(fd, ops);
    188     }
    189 
    190     public Selector wakeup() {
    191         synchronized (interruptLock) {
    192             if (!interruptTriggered) {
    193                 pollWrapper.interrupt();
    194                 interruptTriggered = true;
    195             }
    196         }
    197         return this;
    198     }
    199 }
    200