Home | History | Annotate | Download | only in ch
      1 /*
      2  * Copyright (c) 2001, 2013, 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 abstract selector impl.
     37  */
     38 
     39 abstract class AbstractPollSelectorImpl
     40     extends SelectorImpl
     41 {
     42 
     43     // The poll fd array
     44     PollArrayWrapper pollWrapper;
     45 
     46     // Initial capacity of the pollfd array
     47     protected final int INIT_CAP = 10;
     48 
     49     // The list of SelectableChannels serviced by this Selector
     50     protected SelectionKeyImpl[] channelArray;
     51 
     52     // In some impls the first entry of channelArray is bogus
     53     protected int channelOffset = 0;
     54 
     55     // The number of valid channels in this Selector's poll array
     56     protected int totalChannels;
     57 
     58     // True if this Selector has been closed
     59     private boolean closed = false;
     60 
     61     // Lock for close and cleanup
     62     private Object closeLock = new Object();
     63 
     64     AbstractPollSelectorImpl(SelectorProvider sp, int channels, int offset) {
     65         super(sp);
     66         this.totalChannels = channels;
     67         this.channelOffset = offset;
     68     }
     69 
     70     public void putEventOps(SelectionKeyImpl sk, int ops) {
     71         synchronized (closeLock) {
     72             if (closed)
     73                 throw new ClosedSelectorException();
     74             pollWrapper.putEventOps(sk.getIndex(), ops);
     75         }
     76     }
     77 
     78     public Selector wakeup() {
     79         pollWrapper.interrupt();
     80         return this;
     81     }
     82 
     83     protected abstract int doSelect(long timeout) throws IOException;
     84 
     85     protected void implClose() throws IOException {
     86         synchronized (closeLock) {
     87             if (closed)
     88                 return;
     89             closed = true;
     90             // Deregister channels
     91             for(int i=channelOffset; i<totalChannels; i++) {
     92                 SelectionKeyImpl ski = channelArray[i];
     93                 assert(ski.getIndex() != -1);
     94                 ski.setIndex(-1);
     95                 deregister(ski);
     96                 SelectableChannel selch = channelArray[i].channel();
     97                 if (!selch.isOpen() && !selch.isRegistered())
     98                     ((SelChImpl)selch).kill();
     99             }
    100             implCloseInterrupt();
    101             pollWrapper.free();
    102             pollWrapper = null;
    103             selectedKeys = null;
    104             channelArray = null;
    105             totalChannels = 0;
    106         }
    107     }
    108 
    109     protected abstract void implCloseInterrupt() throws IOException;
    110 
    111     /**
    112      * Copy the information in the pollfd structs into the opss
    113      * of the corresponding Channels. Add the ready keys to the
    114      * ready queue.
    115      */
    116     protected int updateSelectedKeys() {
    117         int numKeysUpdated = 0;
    118         // Skip zeroth entry; it is for interrupts only
    119         for (int i=channelOffset; i<totalChannels; i++) {
    120             int rOps = pollWrapper.getReventOps(i);
    121             if (rOps != 0) {
    122                 SelectionKeyImpl sk = channelArray[i];
    123                 pollWrapper.putReventOps(i, 0);
    124                 if (selectedKeys.contains(sk)) {
    125                     if (sk.channel.translateAndSetReadyOps(rOps, sk)) {
    126                         numKeysUpdated++;
    127                     }
    128                 } else {
    129                     sk.channel.translateAndSetReadyOps(rOps, sk);
    130                     if ((sk.nioReadyOps() & sk.nioInterestOps()) != 0) {
    131                         selectedKeys.add(sk);
    132                         numKeysUpdated++;
    133                     }
    134                 }
    135             }
    136         }
    137         return numKeysUpdated;
    138     }
    139 
    140     protected void implRegister(SelectionKeyImpl ski) {
    141         synchronized (closeLock) {
    142             if (closed)
    143                 throw new ClosedSelectorException();
    144 
    145             // Check to see if the array is large enough
    146             if (channelArray.length == totalChannels) {
    147                 // Make a larger array
    148                 int newSize = pollWrapper.totalChannels * 2;
    149                 SelectionKeyImpl temp[] = new SelectionKeyImpl[newSize];
    150                 // Copy over
    151                 for (int i=channelOffset; i<totalChannels; i++)
    152                     temp[i] = channelArray[i];
    153                 channelArray = temp;
    154                 // Grow the NativeObject poll array
    155                 pollWrapper.grow(newSize);
    156             }
    157             channelArray[totalChannels] = ski;
    158             ski.setIndex(totalChannels);
    159             pollWrapper.addEntry(ski.channel);
    160             totalChannels++;
    161             keys.add(ski);
    162         }
    163     }
    164 
    165     protected void implDereg(SelectionKeyImpl ski) throws IOException {
    166         // Algorithm: Copy the sc from the end of the list and put it into
    167         // the location of the sc to be removed (since order doesn't
    168         // matter). Decrement the sc count. Update the index of the sc
    169         // that is moved.
    170         int i = ski.getIndex();
    171         assert (i >= 0);
    172         if (i != totalChannels - 1) {
    173             // Copy end one over it
    174             SelectionKeyImpl endChannel = channelArray[totalChannels-1];
    175             channelArray[i] = endChannel;
    176             endChannel.setIndex(i);
    177             pollWrapper.release(i);
    178             PollArrayWrapper.replaceEntry(pollWrapper, totalChannels - 1,
    179                                           pollWrapper, i);
    180         } else {
    181             pollWrapper.release(i);
    182         }
    183         // Destroy the last one
    184         channelArray[totalChannels-1] = null;
    185         totalChannels--;
    186         pollWrapper.totalChannels--;
    187         ski.setIndex(-1);
    188         // Remove the key from keys and selectedKeys
    189         keys.remove(ski);
    190         selectedKeys.remove(ski);
    191         deregister((AbstractSelectionKey)ski);
    192         SelectableChannel selch = ski.channel();
    193         if (!selch.isOpen() && !selch.isRegistered())
    194             ((SelChImpl)selch).kill();
    195     }
    196 }
    197