1. /*
  2. * @(#)AbstractSelector.java 1.19 04/05/05
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.nio.channels.spi;
  8. import java.io.IOException;
  9. import java.nio.channels.SelectionKey;
  10. import java.nio.channels.Selector;
  11. import java.util.HashSet;
  12. import java.util.Set;
  13. import sun.nio.ch.Interruptible;
  14. import java.util.concurrent.atomic.AtomicBoolean;
  15. /**
  16. * Base implementation class for selectors.
  17. *
  18. * <p> This class encapsulates the low-level machinery required to implement
  19. * the interruption of selection operations. A concrete selector class must
  20. * invoke the {@link #begin begin} and {@link #end end} methods before and
  21. * after, respectively, invoking an I/O operation that might block
  22. * indefinitely. In order to ensure that the {@link #end end} method is always
  23. * invoked, these methods should be used within a
  24. * <tt>try</tt> ... <tt>finally</tt> block: <a name="be">
  25. *
  26. * <blockquote><pre>
  27. * try {
  28. * begin();
  29. * // Perform blocking I/O operation here
  30. * ...
  31. * } finally {
  32. * end();
  33. * }</pre></blockquote>
  34. *
  35. * <p> This class also defines methods for maintaining a selector's
  36. * cancelled-key set and for removing a key from its channel's key set, and
  37. * declares the abstract {@link #register register} method that is invoked by a
  38. * selectable channel's {@link AbstractSelectableChannel#register register}
  39. * method in order to perform the actual work of registering a channel. </p>
  40. *
  41. *
  42. * @author Mark Reinhold
  43. * @author JSR-51 Expert Group
  44. * @version 1.19, 04/05/05
  45. * @since 1.4
  46. */
  47. public abstract class AbstractSelector
  48. extends Selector
  49. {
  50. private AtomicBoolean selectorOpen = new AtomicBoolean(true);
  51. // The provider that created this selector
  52. private final SelectorProvider provider;
  53. /**
  54. * Initializes a new instance of this class. </p>
  55. */
  56. protected AbstractSelector(SelectorProvider provider) {
  57. this.provider = provider;
  58. }
  59. private final Set cancelledKeys = new HashSet();
  60. void cancel(SelectionKey k) { // package-private
  61. synchronized (cancelledKeys) {
  62. cancelledKeys.add(k);
  63. }
  64. }
  65. /**
  66. * Closes this selector.
  67. *
  68. * <p> If the selector has already been closed then this method returns
  69. * immediately. Otherwise it marks the selector as closed and then invokes
  70. * the {@link #implCloseSelector implCloseSelector} method in order to
  71. * complete the close operation. </p>
  72. *
  73. * @throws IOException
  74. * If an I/O error occurs
  75. */
  76. public final void close() throws IOException {
  77. boolean open = selectorOpen.getAndSet(false);
  78. if (!open)
  79. return;
  80. implCloseSelector();
  81. }
  82. /**
  83. * Closes this selector.
  84. *
  85. * <p> This method is invoked by the {@link #close close} method in order
  86. * to perform the actual work of closing the selector. This method is only
  87. * invoked if the selector has not yet been closed, and it is never invoked
  88. * more than once.
  89. *
  90. * <p> An implementation of this method must arrange for any other thread
  91. * that is blocked in a selection operation upon this selector to return
  92. * immediately as if by invoking the {@link
  93. * java.nio.channels.Selector#wakeup wakeup} method. </p>
  94. *
  95. * @throws IOException
  96. * If an I/O error occurs while closing the selector
  97. */
  98. protected abstract void implCloseSelector() throws IOException;
  99. public final boolean isOpen() {
  100. return selectorOpen.get();
  101. }
  102. /**
  103. * Returns the provider that created this channel.
  104. *
  105. * @return The provider that created this channel
  106. */
  107. public final SelectorProvider provider() {
  108. return provider;
  109. }
  110. /**
  111. * Retrieves this selector's cancelled-key set.
  112. *
  113. * <p> This set should only be used while synchronized upon it. </p>
  114. *
  115. * @return The cancelled-key set
  116. */
  117. protected final Set<SelectionKey> cancelledKeys() {
  118. return cancelledKeys;
  119. }
  120. /**
  121. * Registers the given channel with this selector.
  122. *
  123. * <p> This method is invoked by a channel's {@link
  124. * AbstractSelectableChannel#register register} method in order to perform
  125. * the actual work of registering the channel with this selector. </p>
  126. *
  127. * @param ch
  128. * The channel to be registered
  129. *
  130. * @param ops
  131. * The initial interest set, which must be valid
  132. *
  133. * @param att
  134. * The initial attachment for the resulting key
  135. *
  136. * @return A new key representing the registration of the given channel
  137. * with this selector
  138. */
  139. protected abstract SelectionKey register(AbstractSelectableChannel ch,
  140. int ops, Object att);
  141. /**
  142. * Removes the given key from its channel's key set.
  143. *
  144. * <p> This method must be invoked by the selector for each channel that it
  145. * deregisters. </p>
  146. *
  147. * @param key
  148. * The selection key to be removed
  149. */
  150. protected final void deregister(AbstractSelectionKey key) {
  151. ((AbstractSelectableChannel)key.channel()).removeKey(key);
  152. }
  153. // -- Interruption machinery --
  154. private Interruptible interruptor = null;
  155. /**
  156. * Marks the beginning of an I/O operation that might block indefinitely.
  157. *
  158. * <p> This method should be invoked in tandem with the {@link #end end}
  159. * method, using a <tt>try</tt> ... <tt>finally</tt> block as
  160. * shown <a href="#be">above</a>, in order to implement interruption for
  161. * this selector.
  162. *
  163. * <p> Invoking this method arranges for the selector's {@link
  164. * Selector#wakeup wakeup} method to be invoked if a thread's {@link
  165. * Thread#interrupt interrupt} method is invoked while the thread is
  166. * blocked in an I/O operation upon the selector. </p>
  167. */
  168. protected final void begin() {
  169. if (interruptor == null) {
  170. interruptor = new Interruptible() {
  171. public void interrupt() {
  172. AbstractSelector.this.wakeup();
  173. }};
  174. }
  175. AbstractInterruptibleChannel.blockedOn(interruptor);
  176. if (Thread.currentThread().isInterrupted())
  177. interruptor.interrupt();
  178. }
  179. /**
  180. * Marks the end of an I/O operation that might block indefinitely.
  181. *
  182. * <p> This method should be invoked in tandem with the {@link #end end}
  183. * method, using a <tt>try</tt> ... <tt>finally</tt> block as
  184. * shown <a href="#be">above</a>, in order to implement interruption for
  185. * this selector. </p>
  186. */
  187. protected final void end() {
  188. AbstractInterruptibleChannel.blockedOn(null);
  189. }
  190. }