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