src/java.base/linux/classes/sun/nio/ch/EPollSelectorImpl.java

Print this page




  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  * An implementation of Selector for Linux 2.6+ kernels that uses
  36  * the epoll event notification facility.
  37  */
  38 class EPollSelectorImpl
  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     EPollArrayWrapper pollWrapper;
  48 
  49     // Maps from file descriptors to keys
  50     private Map<Integer,SelectionKeyImpl> fdToKey;
  51 
  52     // True if this Selector has been closed


  54 
  55     // Lock for interrupt triggering and clearing
  56     private final Object interruptLock = new Object();
  57     private boolean interruptTriggered = false;
  58 
  59     /**
  60      * Package private constructor called by factory method in
  61      * the abstract superclass Selector.
  62      */
  63     EPollSelectorImpl(SelectorProvider sp) throws IOException {
  64         super(sp);
  65         long pipeFds = IOUtil.makePipe(false);
  66         fd0 = (int) (pipeFds >>> 32);
  67         fd1 = (int) pipeFds;
  68         pollWrapper = new EPollArrayWrapper();
  69         pollWrapper.initInterrupt(fd0, fd1);
  70         fdToKey = new HashMap<>();
  71     }
  72 
  73     protected int doSelect(long timeout) throws IOException {

































  74         if (closed)
  75             throw new ClosedSelectorException();
  76         processDeregisterQueue();
  77         try {
  78             begin();
  79             pollWrapper.poll(timeout);
  80         } finally {
  81             end();
  82         }
  83         processDeregisterQueue();
  84         int numKeysUpdated = updateSelectedKeys();


  85         if (pollWrapper.interrupted()) {
  86             // Clear the wakeup pipe
  87             pollWrapper.putEventOps(pollWrapper.interruptedIndex(), 0);
  88             synchronized (interruptLock) {
  89                 pollWrapper.clearInterrupted();
  90                 IOUtil.drain(fd0);
  91                 interruptTriggered = false;
  92             }
  93         }
  94         return numKeysUpdated;
  95     }
  96 
  97     /**
  98      * Update the keys whose fd's have been selected by the epoll.
  99      * Add the ready keys to the ready queue.
 100      */
 101     private int updateSelectedKeys() {
 102         int entries = pollWrapper.updated;
 103         int numKeysUpdated = 0;
 104         for (int i=0; i<entries; i++) {
 105             int nextFD = pollWrapper.getDescriptor(i);
 106             SelectionKeyImpl ski = fdToKey.get(Integer.valueOf(nextFD));
 107             // ski is null in the case of an interrupt
 108             if (ski != null) {
 109                 int rOps = pollWrapper.getEventOps(i);
 110                 if (selectedKeys.contains(ski)) {
 111                     if (ski.channel.translateAndSetReadyOps(rOps, ski)) {
 112                         numKeysUpdated++;
 113                     }
 114                 } else {
 115                     ski.channel.translateAndSetReadyOps(rOps, ski);
 116                     if ((ski.nioReadyOps() & ski.nioInterestOps()) != 0) {
 117                         selectedKeys.add(ski);
 118                         numKeysUpdated++;
 119                     }
 120                 }
 121             }
 122         }
 123         return numKeysUpdated;
 124     }
 125 
 126     protected void implClose() throws IOException {
 127         if (closed)
 128             return;
 129         closed = true;
 130 
 131         // prevent further wakeup
 132         synchronized (interruptLock) {
 133             interruptTriggered = true;
 134         }
 135 
 136         FileDispatcherImpl.closeIntFD(fd0);




  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 java.util.function.Consumer;
  33 
  34 /**
  35  * An implementation of Selector for Linux 2.6+ kernels that uses
  36  * the epoll event notification facility.
  37  */
  38 class EPollSelectorImpl
  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     EPollArrayWrapper pollWrapper;
  48 
  49     // Maps from file descriptors to keys
  50     private Map<Integer,SelectionKeyImpl> fdToKey;
  51 
  52     // True if this Selector has been closed


  54 
  55     // Lock for interrupt triggering and clearing
  56     private final Object interruptLock = new Object();
  57     private boolean interruptTriggered = false;
  58 
  59     /**
  60      * Package private constructor called by factory method in
  61      * the abstract superclass Selector.
  62      */
  63     EPollSelectorImpl(SelectorProvider sp) throws IOException {
  64         super(sp);
  65         long pipeFds = IOUtil.makePipe(false);
  66         fd0 = (int) (pipeFds >>> 32);
  67         fd1 = (int) pipeFds;
  68         pollWrapper = new EPollArrayWrapper();
  69         pollWrapper.initInterrupt(fd0, fd1);
  70         fdToKey = new HashMap<>();
  71     }
  72 
  73     protected int doSelect(long timeout) throws IOException {
  74         pollEpollWrapper(timeout);
  75         int numKeysUpdated = updateSelectedKeys();
  76         clearWakeupPipeIfInterrupted();
  77         return numKeysUpdated;
  78     }
  79 
  80     @Override
  81     protected int doSelect(Consumer<SelectionKey> handler, long timeout) throws IOException {
  82         Objects.requireNonNull(handler);
  83         pollEpollWrapper(timeout);
  84         final int entries = pollWrapper.updated;
  85         int numKeysUpdated = 0;
  86         try {
  87             for (int i=0; i<entries; i++) {
  88                 final int nextFD = pollWrapper.getDescriptor(i);
  89                 final SelectionKeyImpl ski = fdToKey.get(nextFD);
  90                 // ski is null in the case of an interrupt
  91                 if (ski != null) {
  92                     final int readyOperations = pollWrapper.getEventOps(i);
  93                     ski.channel.translateAndSetReadyOps(readyOperations, ski);
  94                     if (ski.hasOps()) {
  95                         handler.accept(ski);
  96                         numKeysUpdated++;
  97                     }
  98                 }
  99             }
 100         } finally {
 101             clearWakeupPipeIfInterrupted();
 102         }
 103         return numKeysUpdated;
 104     }
 105 
 106     private void pollEpollWrapper(long timeout) throws IOException {
 107         if (closed)
 108             throw new ClosedSelectorException();
 109         processDeregisterQueue();
 110         try {
 111             begin();
 112             pollWrapper.poll(timeout);
 113         } finally {
 114             end();
 115         }
 116         processDeregisterQueue();
 117     }
 118 
 119     private void clearWakeupPipeIfInterrupted() throws IOException {
 120         if (pollWrapper.interrupted()) {
 121             // Clear the wakeup pipe
 122             pollWrapper.putEventOps(pollWrapper.interruptedIndex(), 0);
 123             synchronized (interruptLock) {
 124                 pollWrapper.clearInterrupted();
 125                 IOUtil.drain(fd0);
 126                 interruptTriggered = false;
 127             }
 128         }

 129     }
 130 
 131     /**
 132      * Update the keys whose fd's have been selected by the epoll.
 133      * Add the ready keys to the ready queue.
 134      */
 135     private int updateSelectedKeys() {
 136         int entries = pollWrapper.updated;
 137         int numKeysUpdated = 0;
 138         for (int i=0; i<entries; i++) {
 139             int nextFD = pollWrapper.getDescriptor(i);
 140             SelectionKeyImpl ski = fdToKey.get(Integer.valueOf(nextFD));
 141             // ski is null in the case of an interrupt
 142             if (ski != null) {
 143                 int readyOperations = pollWrapper.getEventOps(i);
 144                 if (selectedKeys.contains(ski)) {
 145                     if (ski.channel.translateAndSetReadyOps(readyOperations, ski)) {
 146                         numKeysUpdated++;
 147                     }
 148                 } else {
 149                     ski.channel.translateAndSetReadyOps(readyOperations, ski);
 150                     if (ski.hasOps()) {
 151                         selectedKeys.add(ski);
 152                         numKeysUpdated++;
 153                     }
 154                 }
 155             }
 156         }
 157         return numKeysUpdated;
 158     }
 159 
 160     protected void implClose() throws IOException {
 161         if (closed)
 162             return;
 163         closed = true;
 164 
 165         // prevent further wakeup
 166         synchronized (interruptLock) {
 167             interruptTriggered = true;
 168         }
 169 
 170         FileDispatcherImpl.closeIntFD(fd0);