jdk/src/java.base/share/classes/java/nio/channels/spi/AbstractSelector.java
changeset 25859 3317bb8137f4
parent 23010 6dadb192ad81
child 32143 394ab6a6658d
equal deleted inserted replaced
25858:836adbf7a2cd 25859:3317bb8137f4
       
     1 /*
       
     2  * Copyright (c) 2000, 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 java.nio.channels.spi;
       
    27 
       
    28 import java.io.IOException;
       
    29 import java.nio.channels.SelectionKey;
       
    30 import java.nio.channels.Selector;
       
    31 import java.util.HashSet;
       
    32 import java.util.Set;
       
    33 import sun.nio.ch.Interruptible;
       
    34 import java.util.concurrent.atomic.AtomicBoolean;
       
    35 
       
    36 
       
    37 /**
       
    38  * Base implementation class for selectors.
       
    39  *
       
    40  * <p> This class encapsulates the low-level machinery required to implement
       
    41  * the interruption of selection operations.  A concrete selector class must
       
    42  * invoke the {@link #begin begin} and {@link #end end} methods before and
       
    43  * after, respectively, invoking an I/O operation that might block
       
    44  * indefinitely.  In order to ensure that the {@link #end end} method is always
       
    45  * invoked, these methods should be used within a
       
    46  * <tt>try</tt>&nbsp;...&nbsp;<tt>finally</tt> block:
       
    47  *
       
    48  * <blockquote><pre>
       
    49  * try {
       
    50  *     begin();
       
    51  *     // Perform blocking I/O operation here
       
    52  *     ...
       
    53  * } finally {
       
    54  *     end();
       
    55  * }</pre></blockquote>
       
    56  *
       
    57  * <p> This class also defines methods for maintaining a selector's
       
    58  * cancelled-key set and for removing a key from its channel's key set, and
       
    59  * declares the abstract {@link #register register} method that is invoked by a
       
    60  * selectable channel's {@link AbstractSelectableChannel#register register}
       
    61  * method in order to perform the actual work of registering a channel.  </p>
       
    62  *
       
    63  *
       
    64  * @author Mark Reinhold
       
    65  * @author JSR-51 Expert Group
       
    66  * @since 1.4
       
    67  */
       
    68 
       
    69 public abstract class AbstractSelector
       
    70     extends Selector
       
    71 {
       
    72 
       
    73     private AtomicBoolean selectorOpen = new AtomicBoolean(true);
       
    74 
       
    75     // The provider that created this selector
       
    76     private final SelectorProvider provider;
       
    77 
       
    78     /**
       
    79      * Initializes a new instance of this class.
       
    80      *
       
    81      * @param  provider
       
    82      *         The provider that created this selector
       
    83      */
       
    84     protected AbstractSelector(SelectorProvider provider) {
       
    85         this.provider = provider;
       
    86     }
       
    87 
       
    88     private final Set<SelectionKey> cancelledKeys = new HashSet<SelectionKey>();
       
    89 
       
    90     void cancel(SelectionKey k) {                       // package-private
       
    91         synchronized (cancelledKeys) {
       
    92             cancelledKeys.add(k);
       
    93         }
       
    94     }
       
    95 
       
    96     /**
       
    97      * Closes this selector.
       
    98      *
       
    99      * <p> If the selector has already been closed then this method returns
       
   100      * immediately.  Otherwise it marks the selector as closed and then invokes
       
   101      * the {@link #implCloseSelector implCloseSelector} method in order to
       
   102      * complete the close operation.  </p>
       
   103      *
       
   104      * @throws  IOException
       
   105      *          If an I/O error occurs
       
   106      */
       
   107     public final void close() throws IOException {
       
   108         boolean open = selectorOpen.getAndSet(false);
       
   109         if (!open)
       
   110             return;
       
   111         implCloseSelector();
       
   112     }
       
   113 
       
   114     /**
       
   115      * Closes this selector.
       
   116      *
       
   117      * <p> This method is invoked by the {@link #close close} method in order
       
   118      * to perform the actual work of closing the selector.  This method is only
       
   119      * invoked if the selector has not yet been closed, and it is never invoked
       
   120      * more than once.
       
   121      *
       
   122      * <p> An implementation of this method must arrange for any other thread
       
   123      * that is blocked in a selection operation upon this selector to return
       
   124      * immediately as if by invoking the {@link
       
   125      * java.nio.channels.Selector#wakeup wakeup} method. </p>
       
   126      *
       
   127      * @throws  IOException
       
   128      *          If an I/O error occurs while closing the selector
       
   129      */
       
   130     protected abstract void implCloseSelector() throws IOException;
       
   131 
       
   132     public final boolean isOpen() {
       
   133         return selectorOpen.get();
       
   134     }
       
   135 
       
   136     /**
       
   137      * Returns the provider that created this channel.
       
   138      *
       
   139      * @return  The provider that created this channel
       
   140      */
       
   141     public final SelectorProvider provider() {
       
   142         return provider;
       
   143     }
       
   144 
       
   145     /**
       
   146      * Retrieves this selector's cancelled-key set.
       
   147      *
       
   148      * <p> This set should only be used while synchronized upon it.  </p>
       
   149      *
       
   150      * @return  The cancelled-key set
       
   151      */
       
   152     protected final Set<SelectionKey> cancelledKeys() {
       
   153         return cancelledKeys;
       
   154     }
       
   155 
       
   156     /**
       
   157      * Registers the given channel with this selector.
       
   158      *
       
   159      * <p> This method is invoked by a channel's {@link
       
   160      * AbstractSelectableChannel#register register} method in order to perform
       
   161      * the actual work of registering the channel with this selector.  </p>
       
   162      *
       
   163      * @param  ch
       
   164      *         The channel to be registered
       
   165      *
       
   166      * @param  ops
       
   167      *         The initial interest set, which must be valid
       
   168      *
       
   169      * @param  att
       
   170      *         The initial attachment for the resulting key
       
   171      *
       
   172      * @return  A new key representing the registration of the given channel
       
   173      *          with this selector
       
   174      */
       
   175     protected abstract SelectionKey register(AbstractSelectableChannel ch,
       
   176                                              int ops, Object att);
       
   177 
       
   178     /**
       
   179      * Removes the given key from its channel's key set.
       
   180      *
       
   181      * <p> This method must be invoked by the selector for each channel that it
       
   182      * deregisters.  </p>
       
   183      *
       
   184      * @param  key
       
   185      *         The selection key to be removed
       
   186      */
       
   187     protected final void deregister(AbstractSelectionKey key) {
       
   188         ((AbstractSelectableChannel)key.channel()).removeKey(key);
       
   189     }
       
   190 
       
   191 
       
   192     // -- Interruption machinery --
       
   193 
       
   194     private Interruptible interruptor = null;
       
   195 
       
   196     /**
       
   197      * Marks the beginning of an I/O operation that might block indefinitely.
       
   198      *
       
   199      * <p> This method should be invoked in tandem with the {@link #end end}
       
   200      * method, using a <tt>try</tt>&nbsp;...&nbsp;<tt>finally</tt> block as
       
   201      * shown <a href="#be">above</a>, in order to implement interruption for
       
   202      * this selector.
       
   203      *
       
   204      * <p> Invoking this method arranges for the selector's {@link
       
   205      * Selector#wakeup wakeup} method to be invoked if a thread's {@link
       
   206      * Thread#interrupt interrupt} method is invoked while the thread is
       
   207      * blocked in an I/O operation upon the selector.  </p>
       
   208      */
       
   209     protected final void begin() {
       
   210         if (interruptor == null) {
       
   211             interruptor = new Interruptible() {
       
   212                     public void interrupt(Thread ignore) {
       
   213                         AbstractSelector.this.wakeup();
       
   214                     }};
       
   215         }
       
   216         AbstractInterruptibleChannel.blockedOn(interruptor);
       
   217         Thread me = Thread.currentThread();
       
   218         if (me.isInterrupted())
       
   219             interruptor.interrupt(me);
       
   220     }
       
   221 
       
   222     /**
       
   223      * Marks the end of an I/O operation that might block indefinitely.
       
   224      *
       
   225      * <p> This method should be invoked in tandem with the {@link #begin begin}
       
   226      * method, using a <tt>try</tt>&nbsp;...&nbsp;<tt>finally</tt> block as
       
   227      * shown <a href="#be">above</a>, in order to implement interruption for
       
   228      * this selector.  </p>
       
   229      */
       
   230     protected final void end() {
       
   231         AbstractInterruptibleChannel.blockedOn(null);
       
   232     }
       
   233 
       
   234 }