- /*
 - * @(#)AbstractSelector.java 1.16 03/01/23
 - *
 - * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
 - * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 - */
 - package java.nio.channels.spi;
 - import java.io.IOException;
 - import java.nio.channels.SelectionKey;
 - import java.nio.channels.Selector;
 - import java.util.HashSet;
 - import java.util.Set;
 - import sun.nio.ch.Interruptible;
 - /**
 - * Base implementation class for selectors.
 - *
 - * <p> This class encapsulates the low-level machinery required to implement
 - * the interruption of selection operations. A concrete selector class must
 - * invoke the {@link #begin begin} and {@link #end end} methods before and
 - * after, respectively, invoking an I/O operation that might block
 - * indefinitely. In order to ensure that the {@link #end end} method is always
 - * invoked, these methods should be used within a
 - * <tt>try</tt> ... <tt>finally</tt> block: <a name="be">
 - *
 - * <blockquote><pre>
 - * try {
 - * begin();
 - * // Perform blocking I/O operation here
 - * ...
 - * } finally {
 - * end();
 - * }</pre></blockquote>
 - *
 - * <p> This class also defines methods for maintaining a selector's
 - * cancelled-key set and for removing a key from its channel's key set, and
 - * declares the abstract {@link #register register} method that is invoked by a
 - * selectable channel's {@link AbstractSelectableChannel#register register}
 - * method in order to perform the actual work of registering a channel. </p>
 - *
 - *
 - * @author Mark Reinhold
 - * @author JSR-51 Expert Group
 - * @version 1.16, 03/01/23
 - * @since 1.4
 - */
 - public abstract class AbstractSelector
 - extends Selector
 - {
 - private boolean open = true;
 - // The provider that created this selector
 - private final SelectorProvider provider;
 - /**
 - * Initializes a new instance of this class. </p>
 - */
 - protected AbstractSelector(SelectorProvider provider) {
 - this.provider = provider;
 - }
 - private final Set cancelledKeys = new HashSet();
 - void cancel(SelectionKey k) { // package-private
 - synchronized (cancelledKeys) {
 - cancelledKeys.add(k);
 - }
 - }
 - /**
 - * Closes this selector.
 - *
 - * <p> If the selector has already been closed then this method returns
 - * immediately. Otherwise it marks the selector as closed and then invokes
 - * the {@link #implCloseSelector implCloseSelector} method in order to
 - * complete the close operation. </p>
 - *
 - * @throws IOException
 - * If an I/O error occurs
 - */
 - public final void close() throws IOException {
 - synchronized (this) {
 - if (!open)
 - return;
 - open = false;
 - implCloseSelector();
 - }
 - }
 - /**
 - * Closes this selector.
 - *
 - * <p> This method is invoked by the {@link #close close} method in order
 - * to perform the actual work of closing the selector. This method is only
 - * invoked if the selector has not yet been closed, and it is never invoked
 - * more than once.
 - *
 - * <p> An implementation of this method must arrange for any other thread
 - * that is blocked in a selection operation upon this selector to return
 - * immediately as if by invoking the {@link
 - * java.nio.channels.Selector#wakeup wakeup} method. </p>
 - *
 - * @throws IOException
 - * If an I/O error occurs while closing the selector
 - */
 - protected abstract void implCloseSelector() throws IOException;
 - public final boolean isOpen() {
 - return open;
 - }
 - /**
 - * Returns the provider that created this channel.
 - *
 - * @return The provider that created this channel
 - */
 - public final SelectorProvider provider() {
 - return provider;
 - }
 - /**
 - * Retrieves this selector's cancelled-key set.
 - *
 - * <p> This set should only be used while synchronized upon it. </p>
 - *
 - * @return The cancelled-key set
 - */
 - protected final Set cancelledKeys() {
 - return cancelledKeys;
 - }
 - /**
 - * Registers the given channel with this selector.
 - *
 - * <p> This method is invoked by a channel's {@link
 - * AbstractSelectableChannel#register register} method in order to perform
 - * the actual work of registering the channel with this selector. </p>
 - *
 - * @param ch
 - * The channel to be registered
 - *
 - * @param ops
 - * The initial interest set, which must be valid
 - *
 - * @param att
 - * The initial attachment for the resulting key
 - *
 - * @return A new key representing the registration of the given channel
 - * with this selector
 - */
 - protected abstract SelectionKey register(AbstractSelectableChannel ch,
 - int ops, Object att);
 - /**
 - * Removes the given key from its channel's key set.
 - *
 - * <p> This method must be invoked by the selector for each channel that it
 - * deregisters. </p>
 - *
 - * @param key
 - * The selection key to be removed
 - */
 - protected final void deregister(AbstractSelectionKey key) {
 - ((AbstractSelectableChannel)key.channel()).removeKey(key);
 - }
 - // -- Interruption machinery --
 - private Interruptible interruptor = null;
 - /**
 - * Marks the beginning of an I/O operation that might block indefinitely.
 - *
 - * <p> This method should be invoked in tandem with the {@link #end end}
 - * method, using a <tt>try</tt> ... <tt>finally</tt> block as
 - * shown <a href="#be">above</a>, in order to implement interruption for
 - * this selector.
 - *
 - * <p> Invoking this method arranges for the selector's {@link
 - * Selector#wakeup wakeup} method to be invoked if a thread's {@link
 - * Thread#interrupt interrupt} method is invoked while the thread is
 - * blocked in an I/O operation upon the selector. </p>
 - */
 - protected final void begin() {
 - if (interruptor == null) {
 - interruptor = new Interruptible() {
 - public void interrupt() {
 - AbstractSelector.this.wakeup();
 - }};
 - }
 - AbstractInterruptibleChannel.blockedOn(interruptor);
 - if (Thread.currentThread().isInterrupted())
 - interruptor.interrupt();
 - }
 - /**
 - * Marks the end of an I/O operation that might block indefinitely.
 - *
 - * <p> This method should be invoked in tandem with the {@link #end end}
 - * method, using a <tt>try</tt> ... <tt>finally</tt> block as
 - * shown <a href="#be">above</a>, in order to implement interruption for
 - * this selector. </p>
 - */
 - protected final void end() {
 - AbstractInterruptibleChannel.blockedOn(null);
 - }
 - }