|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  */ | 
|  |  | 
|  | package sun.nio.ch; | 
|  |  | 
|  | import java.io.IOException; | 
|  | import java.nio.channels.*; | 
|  | import java.nio.channels.spi.*; | 
|  | import java.util.*; | 
|  | import sun.misc.*; | 
|  |  | 
|  |  | 
|  | /** | 
|  |  * An abstract selector impl. | 
|  |  */ | 
|  |  | 
|  | abstract class AbstractPollSelectorImpl | 
|  |     extends SelectorImpl | 
|  | { | 
|  |  | 
|  |      | 
|  |     PollArrayWrapper pollWrapper; | 
|  |  | 
|  |      | 
|  |     protected final int INIT_CAP = 10; | 
|  |  | 
|  |      | 
|  |     protected SelectionKeyImpl[] channelArray; | 
|  |  | 
|  |      | 
|  |     protected int channelOffset = 0; | 
|  |  | 
|  |      | 
|  |     protected int totalChannels; | 
|  |  | 
|  |      | 
|  |     private boolean closed = false; | 
|  |  | 
|  |      | 
|  |     private Object closeLock = new Object(); | 
|  |  | 
|  |     AbstractPollSelectorImpl(SelectorProvider sp, int channels, int offset) { | 
|  |         super(sp); | 
|  |         this.totalChannels = channels; | 
|  |         this.channelOffset = offset; | 
|  |     } | 
|  |  | 
|  |     public void putEventOps(SelectionKeyImpl sk, int ops) { | 
|  |         synchronized (closeLock) { | 
|  |             if (closed) | 
|  |                 throw new ClosedSelectorException(); | 
|  |             pollWrapper.putEventOps(sk.getIndex(), ops); | 
|  |         } | 
|  |     } | 
|  |  | 
|  |     public Selector wakeup() { | 
|  |         pollWrapper.interrupt(); | 
|  |         return this; | 
|  |     } | 
|  |  | 
|  |     protected abstract int doSelect(long timeout) throws IOException; | 
|  |  | 
|  |     protected void implClose() throws IOException { | 
|  |         synchronized (closeLock) { | 
|  |             if (closed) | 
|  |                 return; | 
|  |             closed = true; | 
|  |              | 
|  |             for(int i=channelOffset; i<totalChannels; i++) { | 
|  |                 SelectionKeyImpl ski = channelArray[i]; | 
|  |                 assert(ski.getIndex() != -1); | 
|  |                 ski.setIndex(-1); | 
|  |                 deregister(ski); | 
|  |                 SelectableChannel selch = channelArray[i].channel(); | 
|  |                 if (!selch.isOpen() && !selch.isRegistered()) | 
|  |                     ((SelChImpl)selch).kill(); | 
|  |             } | 
|  |             implCloseInterrupt(); | 
|  |             pollWrapper.free(); | 
|  |             pollWrapper = null; | 
|  |             selectedKeys = null; | 
|  |             channelArray = null; | 
|  |             totalChannels = 0; | 
|  |         } | 
|  |     } | 
|  |  | 
|  |     protected abstract void implCloseInterrupt() throws IOException; | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     protected int updateSelectedKeys() { | 
|  |         int numKeysUpdated = 0; | 
|  |          | 
|  |         for (int i=channelOffset; i<totalChannels; i++) { | 
|  |             int rOps = pollWrapper.getReventOps(i); | 
|  |             if (rOps != 0) { | 
|  |                 SelectionKeyImpl sk = channelArray[i]; | 
|  |                 pollWrapper.putReventOps(i, 0); | 
|  |                 if (selectedKeys.contains(sk)) { | 
|  |                     if (sk.channel.translateAndSetReadyOps(rOps, sk)) { | 
|  |                         numKeysUpdated++; | 
|  |                     } | 
|  |                 } else { | 
|  |                     sk.channel.translateAndSetReadyOps(rOps, sk); | 
|  |                     if ((sk.nioReadyOps() & sk.nioInterestOps()) != 0) { | 
|  |                         selectedKeys.add(sk); | 
|  |                         numKeysUpdated++; | 
|  |                     } | 
|  |                 } | 
|  |             } | 
|  |         } | 
|  |         return numKeysUpdated; | 
|  |     } | 
|  |  | 
|  |     protected void implRegister(SelectionKeyImpl ski) { | 
|  |         synchronized (closeLock) { | 
|  |             if (closed) | 
|  |                 throw new ClosedSelectorException(); | 
|  |  | 
|  |              | 
|  |             if (channelArray.length == totalChannels) { | 
|  |                  | 
|  |                 int newSize = pollWrapper.totalChannels * 2; | 
|  |                 SelectionKeyImpl temp[] = new SelectionKeyImpl[newSize]; | 
|  |                  | 
|  |                 for (int i=channelOffset; i<totalChannels; i++) | 
|  |                     temp[i] = channelArray[i]; | 
|  |                 channelArray = temp; | 
|  |                  | 
|  |                 pollWrapper.grow(newSize); | 
|  |             } | 
|  |             channelArray[totalChannels] = ski; | 
|  |             ski.setIndex(totalChannels); | 
|  |             pollWrapper.addEntry(ski.channel); | 
|  |             totalChannels++; | 
|  |             keys.add(ski); | 
|  |         } | 
|  |     } | 
|  |  | 
|  |     protected void implDereg(SelectionKeyImpl ski) throws IOException { | 
|  |         // Algorithm: Copy the sc from the end of the list and put it into | 
|  |         // the location of the sc to be removed (since order doesn't | 
|  |         // matter). Decrement the sc count. Update the index of the sc | 
|  |          | 
|  |         int i = ski.getIndex(); | 
|  |         assert (i >= 0); | 
|  |         if (i != totalChannels - 1) { | 
|  |              | 
|  |             SelectionKeyImpl endChannel = channelArray[totalChannels-1]; | 
|  |             channelArray[i] = endChannel; | 
|  |             endChannel.setIndex(i); | 
|  |             pollWrapper.release(i); | 
|  |             PollArrayWrapper.replaceEntry(pollWrapper, totalChannels - 1, | 
|  |                                           pollWrapper, i); | 
|  |         } else { | 
|  |             pollWrapper.release(i); | 
|  |         } | 
|  |          | 
|  |         channelArray[totalChannels-1] = null; | 
|  |         totalChannels--; | 
|  |         pollWrapper.totalChannels--; | 
|  |         ski.setIndex(-1); | 
|  |          | 
|  |         keys.remove(ski); | 
|  |         selectedKeys.remove(ski); | 
|  |         deregister((AbstractSelectionKey)ski); | 
|  |         SelectableChannel selch = ski.channel(); | 
|  |         if (!selch.isOpen() && !selch.isRegistered()) | 
|  |             ((SelChImpl)selch).kill(); | 
|  |     } | 
|  | } |