src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java
changeset 49493 814bd31f8da0
parent 49417 1d3139252c1c
child 49526 cad4c844902a
equal deleted inserted replaced
49492:f1a8ec1a6972 49493:814bd31f8da0
    25 
    25 
    26 package sun.nio.ch;
    26 package sun.nio.ch;
    27 
    27 
    28 import java.io.IOException;
    28 import java.io.IOException;
    29 import java.nio.channels.ClosedSelectorException;
    29 import java.nio.channels.ClosedSelectorException;
    30 import java.nio.channels.SelectableChannel;
       
    31 import java.nio.channels.SelectionKey;
       
    32 import java.nio.channels.Selector;
    30 import java.nio.channels.Selector;
    33 import java.nio.channels.spi.SelectorProvider;
    31 import java.nio.channels.spi.SelectorProvider;
    34 import java.util.ArrayDeque;
    32 import java.util.ArrayDeque;
    35 import java.util.BitSet;
       
    36 import java.util.Deque;
    33 import java.util.Deque;
    37 import java.util.HashMap;
    34 import java.util.HashMap;
    38 import java.util.Iterator;
       
    39 import java.util.Map;
    35 import java.util.Map;
    40 import java.util.concurrent.TimeUnit;
    36 import java.util.concurrent.TimeUnit;
    41 
    37 
    42 import static sun.nio.ch.DevPollArrayWrapper.NUM_POLLFDS;
    38 import static sun.nio.ch.DevPollArrayWrapper.NUM_POLLFDS;
    43 import static sun.nio.ch.DevPollArrayWrapper.POLLREMOVE;
    39 import static sun.nio.ch.DevPollArrayWrapper.POLLREMOVE;
    57     private final int fd1;
    53     private final int fd1;
    58 
    54 
    59     // maps file descriptor to selection key, synchronize on selector
    55     // maps file descriptor to selection key, synchronize on selector
    60     private final Map<Integer, SelectionKeyImpl> fdToKey = new HashMap<>();
    56     private final Map<Integer, SelectionKeyImpl> fdToKey = new HashMap<>();
    61 
    57 
    62     // file descriptors registered with /dev/poll, synchronize on selector
       
    63     private final BitSet registered = new BitSet();
       
    64 
       
    65     // pending new registrations/updates, queued by implRegister and putEventOps
    58     // pending new registrations/updates, queued by implRegister and putEventOps
    66     private final Object updateLock = new Object();
    59     private final Object updateLock = new Object();
    67     private final Deque<SelectionKeyImpl> newKeys = new ArrayDeque<>();
    60     private final Deque<SelectionKeyImpl> newKeys = new ArrayDeque<>();
    68     private final Deque<SelectionKeyImpl> updateKeys = new ArrayDeque<>();
    61     private final Deque<SelectionKeyImpl> updateKeys = new ArrayDeque<>();
    69     private final Deque<Integer> updateOps = new ArrayDeque<>();
    62     private final Deque<Integer> updateEvents = new ArrayDeque<>();
    70 
    63 
    71     // interrupt triggering and clearing
    64     // interrupt triggering and clearing
    72     private final Object interruptLock = new Object();
    65     private final Object interruptLock = new Object();
    73     private boolean interruptTriggered;
    66     private boolean interruptTriggered;
    74 
    67 
    97     @Override
    90     @Override
    98     protected int doSelect(long timeout)
    91     protected int doSelect(long timeout)
    99         throws IOException
    92         throws IOException
   100     {
    93     {
   101         assert Thread.holdsLock(this);
    94         assert Thread.holdsLock(this);
       
    95         boolean blocking = (timeout != 0);
   102 
    96 
   103         int numEntries;
    97         int numEntries;
   104         processUpdateQueue();
    98         processUpdateQueue();
   105         processDeregisterQueue();
    99         processDeregisterQueue();
   106         try {
   100         try {
   107             begin();
   101             begin(blocking);
   108             numEntries = pollWrapper.poll(timeout);
   102             numEntries = pollWrapper.poll(timeout);
   109         } finally {
   103         } finally {
   110             end();
   104             end(blocking);
   111         }
   105         }
   112         processDeregisterQueue();
   106         processDeregisterQueue();
   113         return updateSelectedKeys(numEntries);
   107         return updateSelectedKeys(numEntries);
   114     }
   108     }
   115 
   109 
   123             SelectionKeyImpl ski;
   117             SelectionKeyImpl ski;
   124 
   118 
   125             // new registrations
   119             // new registrations
   126             while ((ski = newKeys.pollFirst()) != null) {
   120             while ((ski = newKeys.pollFirst()) != null) {
   127                 if (ski.isValid()) {
   121                 if (ski.isValid()) {
   128                     SelChImpl ch = ski.channel;
   122                     int fd = ski.channel.getFDVal();
   129                     int fd = ch.getFDVal();
       
   130                     SelectionKeyImpl previous = fdToKey.put(fd, ski);
   123                     SelectionKeyImpl previous = fdToKey.put(fd, ski);
   131                     assert previous == null;
   124                     assert previous == null;
   132                     assert registered.get(fd) == false;
   125                     assert ski.registeredEvents() == 0;
   133                 }
   126                 }
   134             }
   127             }
   135 
   128 
   136             // Translate the queued updates to changes to the set of monitored
   129             // Translate the queued updates to changes to the set of monitored
   137             // file descriptors. The changes are written to the /dev/poll driver
   130             // file descriptors. The changes are written to the /dev/poll driver
   138             // in bulk.
   131             // in bulk.
   139             assert updateKeys.size() == updateOps.size();
   132             assert updateKeys.size() == updateEvents.size();
   140             int index = 0;
   133             int index = 0;
   141             while ((ski = updateKeys.pollFirst()) != null) {
   134             while ((ski = updateKeys.pollFirst()) != null) {
   142                 int ops = updateOps.pollFirst();
   135                 int newEvents = updateEvents.pollFirst();
   143                 int fd = ski.channel.getFDVal();
   136                 int fd = ski.channel.getFDVal();
   144                 if (ski.isValid() && fdToKey.containsKey(fd)) {
   137                 if (ski.isValid() && fdToKey.containsKey(fd)) {
   145                     if (registered.get(fd)) {
   138                     int registeredEvents = ski.registeredEvents();
   146                         if (ops == 0) {
   139                     if (newEvents != registeredEvents) {
   147                             // remove file descriptor
   140                         if (registeredEvents != 0)
   148                             pollWrapper.putPollFD(index++, fd, POLLREMOVE);
   141                             pollWrapper.putPollFD(index++, fd, POLLREMOVE);
   149                             registered.clear(fd);
   142                         if (newEvents != 0)
   150                         } else {
   143                             pollWrapper.putPollFD(index++, fd, (short)newEvents);
   151                             // change events
   144                         ski.registeredEvents(newEvents);
   152                             pollWrapper.putPollFD(index++, fd, POLLREMOVE);
   145 
   153                             pollWrapper.putPollFD(index++, fd, (short)ops);
   146                         // write to /dev/poll
       
   147                         if (index > (NUM_POLLFDS-2)) {
       
   148                             pollWrapper.registerMultiple(index);
       
   149                             index = 0;
   154                         }
   150                         }
   155                     } else if (ops != 0) {
       
   156                         // add file descriptor
       
   157                         pollWrapper.putPollFD(index++, fd, (short)ops);
       
   158                         registered.set(fd);
       
   159                     }
       
   160                     if (index > (NUM_POLLFDS-2)) {
       
   161                         pollWrapper.registerMultiple(index);
       
   162                         index = 0;
       
   163                     }
   151                     }
   164                 }
   152                 }
   165             }
   153             }
   166 
   154 
   167             // write any remaining changes
   155             // write any remaining changes
   169                 pollWrapper.registerMultiple(index);
   157                 pollWrapper.registerMultiple(index);
   170         }
   158         }
   171     }
   159     }
   172 
   160 
   173     /**
   161     /**
   174      * Update the keys whose fd's have been selected by the /dev/poll.
   162      * Update the keys of file descriptors that were polled and add them to
   175      * Add the ready keys to the ready queue.
   163      * the selected-key set.
       
   164      * If the interrupt fd has been selected, drain it and clear the interrupt.
   176      */
   165      */
   177     private int updateSelectedKeys(int numEntries) throws IOException {
   166     private int updateSelectedKeys(int numEntries) throws IOException {
   178         assert Thread.holdsLock(this);
   167         assert Thread.holdsLock(this);
   179         assert Thread.holdsLock(nioSelectedKeys());
   168         assert Thread.holdsLock(nioSelectedKeys());
   180 
   169 
   212 
   201 
   213     @Override
   202     @Override
   214     protected void implClose() throws IOException {
   203     protected void implClose() throws IOException {
   215         assert !isOpen();
   204         assert !isOpen();
   216         assert Thread.holdsLock(this);
   205         assert Thread.holdsLock(this);
   217         assert Thread.holdsLock(nioKeys());
       
   218 
   206 
   219         // prevent further wakeup
   207         // prevent further wakeup
   220         synchronized (interruptLock) {
   208         synchronized (interruptLock) {
   221             interruptTriggered = true;
   209             interruptTriggered = true;
   222         }
   210         }
   223 
   211 
   224         pollWrapper.close();
   212         pollWrapper.close();
   225         FileDispatcherImpl.closeIntFD(fd0);
   213         FileDispatcherImpl.closeIntFD(fd0);
   226         FileDispatcherImpl.closeIntFD(fd1);
   214         FileDispatcherImpl.closeIntFD(fd1);
   227 
       
   228         // Deregister channels
       
   229         Iterator<SelectionKey> i = keys.iterator();
       
   230         while (i.hasNext()) {
       
   231             SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
       
   232             deregister(ski);
       
   233             SelectableChannel selch = ski.channel();
       
   234             if (!selch.isOpen() && !selch.isRegistered())
       
   235                 ((SelChImpl)selch).kill();
       
   236             i.remove();
       
   237         }
       
   238     }
   215     }
   239 
   216 
   240     @Override
   217     @Override
   241     protected void implRegister(SelectionKeyImpl ski) {
   218     protected void implRegister(SelectionKeyImpl ski) {
   242         assert Thread.holdsLock(nioKeys());
       
   243         ensureOpen();
   219         ensureOpen();
   244         synchronized (updateLock) {
   220         synchronized (updateLock) {
   245             newKeys.addLast(ski);
   221             newKeys.addLast(ski);
   246         }
   222         }
   247         keys.add(ski);
       
   248     }
   223     }
   249 
   224 
   250     @Override
   225     @Override
   251     protected void implDereg(SelectionKeyImpl ski) throws IOException {
   226     protected void implDereg(SelectionKeyImpl ski) throws IOException {
   252         assert !ski.isValid();
   227         assert !ski.isValid();
   253         assert Thread.holdsLock(this);
   228         assert Thread.holdsLock(this);
   254         assert Thread.holdsLock(nioKeys());
       
   255         assert Thread.holdsLock(nioSelectedKeys());
       
   256 
   229 
   257         int fd = ski.channel.getFDVal();
   230         int fd = ski.channel.getFDVal();
   258         fdToKey.remove(fd);
   231         if (fdToKey.remove(fd) != null) {
   259         if (registered.get(fd)) {
   232             if (ski.registeredEvents() != 0) {
   260             pollWrapper.register(fd, POLLREMOVE);
   233                 pollWrapper.register(fd, POLLREMOVE);
   261             registered.clear(fd);
   234                 ski.registeredEvents(0);
   262         }
   235             }
   263 
   236         } else {
   264         selectedKeys.remove(ski);
   237             assert ski.registeredEvents() == 0;
   265         keys.remove(ski);
   238         }
   266 
   239     }
   267         // remove from channel's key set
   240 
   268         deregister(ski);
   241     @Override
   269 
   242     public void putEventOps(SelectionKeyImpl ski, int events) {
   270         SelectableChannel selch = ski.channel();
       
   271         if (!selch.isOpen() && !selch.isRegistered())
       
   272             ((SelChImpl) selch).kill();
       
   273     }
       
   274 
       
   275     @Override
       
   276     public void putEventOps(SelectionKeyImpl ski, int ops) {
       
   277         ensureOpen();
   243         ensureOpen();
   278         synchronized (updateLock) {
   244         synchronized (updateLock) {
   279             updateOps.addLast(ops);   // ops first in case adding the key fails
   245             updateEvents.addLast(events);   // events first in case adding key fails
   280             updateKeys.addLast(ski);
   246             updateKeys.addLast(ski);
   281         }
   247         }
   282     }
   248     }
   283 
   249 
   284     @Override
   250     @Override