KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > nio > channels > spi > AbstractSelector


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
8 package java.nio.channels.spi;
9
10 import java.io.IOException JavaDoc;
11 import java.nio.channels.SelectionKey JavaDoc;
12 import java.nio.channels.Selector JavaDoc;
13 import java.util.HashSet JavaDoc;
14 import java.util.Set JavaDoc;
15 import sun.nio.ch.Interruptible;
16 import java.util.concurrent.atomic.AtomicBoolean JavaDoc;
17
18
19 /**
20  * Base implementation class for selectors.
21  *
22  * <p> This class encapsulates the low-level machinery required to implement
23  * the interruption of selection operations. A concrete selector class must
24  * invoke the {@link #begin begin} and {@link #end end} methods before and
25  * after, respectively, invoking an I/O operation that might block
26  * indefinitely. In order to ensure that the {@link #end end} method is always
27  * invoked, these methods should be used within a
28  * <tt>try</tt>&nbsp;...&nbsp;<tt>finally</tt> block: <a name="be">
29  *
30  * <blockquote><pre>
31  * try {
32  * begin();
33  * // Perform blocking I/O operation here
34  * ...
35  * } finally {
36  * end();
37  * }</pre></blockquote>
38  *
39  * <p> This class also defines methods for maintaining a selector's
40  * cancelled-key set and for removing a key from its channel's key set, and
41  * declares the abstract {@link #register register} method that is invoked by a
42  * selectable channel's {@link AbstractSelectableChannel#register register}
43  * method in order to perform the actual work of registering a channel. </p>
44  *
45  *
46  * @author Mark Reinhold
47  * @author JSR-51 Expert Group
48  * @version 1.19, 04/05/05
49  * @since 1.4
50  */

51
52 public abstract class AbstractSelector
53     extends Selector JavaDoc
54 {
55
56     private AtomicBoolean JavaDoc selectorOpen = new AtomicBoolean JavaDoc(true);
57
58     // The provider that created this selector
59
private final SelectorProvider JavaDoc provider;
60
61     /**
62      * Initializes a new instance of this class. </p>
63      */

64     protected AbstractSelector(SelectorProvider JavaDoc provider) {
65     this.provider = provider;
66     }
67
68     private final Set JavaDoc cancelledKeys = new HashSet JavaDoc();
69
70     void cancel(SelectionKey JavaDoc k) { // package-private
71
synchronized (cancelledKeys) {
72         cancelledKeys.add(k);
73     }
74     }
75
76     /**
77      * Closes this selector.
78      *
79      * <p> If the selector has already been closed then this method returns
80      * immediately. Otherwise it marks the selector as closed and then invokes
81      * the {@link #implCloseSelector implCloseSelector} method in order to
82      * complete the close operation. </p>
83      *
84      * @throws IOException
85      * If an I/O error occurs
86      */

87     public final void close() throws IOException JavaDoc {
88         boolean open = selectorOpen.getAndSet(false);
89         if (!open)
90             return;
91         implCloseSelector();
92     }
93
94     /**
95      * Closes this selector.
96      *
97      * <p> This method is invoked by the {@link #close close} method in order
98      * to perform the actual work of closing the selector. This method is only
99      * invoked if the selector has not yet been closed, and it is never invoked
100      * more than once.
101      *
102      * <p> An implementation of this method must arrange for any other thread
103      * that is blocked in a selection operation upon this selector to return
104      * immediately as if by invoking the {@link
105      * java.nio.channels.Selector#wakeup wakeup} method. </p>
106      *
107      * @throws IOException
108      * If an I/O error occurs while closing the selector
109      */

110     protected abstract void implCloseSelector() throws IOException JavaDoc;
111
112     public final boolean isOpen() {
113     return selectorOpen.get();
114     }
115
116     /**
117      * Returns the provider that created this channel.
118      *
119      * @return The provider that created this channel
120      */

121     public final SelectorProvider JavaDoc provider() {
122     return provider;
123     }
124
125     /**
126      * Retrieves this selector's cancelled-key set.
127      *
128      * <p> This set should only be used while synchronized upon it. </p>
129      *
130      * @return The cancelled-key set
131      */

132     protected final Set JavaDoc<SelectionKey JavaDoc> cancelledKeys() {
133     return cancelledKeys;
134     }
135
136     /**
137      * Registers the given channel with this selector.
138      *
139      * <p> This method is invoked by a channel's {@link
140      * AbstractSelectableChannel#register register} method in order to perform
141      * the actual work of registering the channel with this selector. </p>
142      *
143      * @param ch
144      * The channel to be registered
145      *
146      * @param ops
147      * The initial interest set, which must be valid
148      *
149      * @param att
150      * The initial attachment for the resulting key
151      *
152      * @return A new key representing the registration of the given channel
153      * with this selector
154      */

155     protected abstract SelectionKey JavaDoc register(AbstractSelectableChannel JavaDoc ch,
156                          int ops, Object JavaDoc att);
157
158     /**
159      * Removes the given key from its channel's key set.
160      *
161      * <p> This method must be invoked by the selector for each channel that it
162      * deregisters. </p>
163      *
164      * @param key
165      * The selection key to be removed
166      */

167     protected final void deregister(AbstractSelectionKey JavaDoc key) {
168     ((AbstractSelectableChannel JavaDoc)key.channel()).removeKey(key);
169     }
170
171
172     // -- Interruption machinery --
173

174     private Interruptible interruptor = null;
175
176     /**
177      * Marks the beginning of an I/O operation that might block indefinitely.
178      *
179      * <p> This method should be invoked in tandem with the {@link #end end}
180      * method, using a <tt>try</tt>&nbsp;...&nbsp;<tt>finally</tt> block as
181      * shown <a HREF="#be">above</a>, in order to implement interruption for
182      * this selector.
183      *
184      * <p> Invoking this method arranges for the selector's {@link
185      * Selector#wakeup wakeup} method to be invoked if a thread's {@link
186      * Thread#interrupt interrupt} method is invoked while the thread is
187      * blocked in an I/O operation upon the selector. </p>
188      */

189     protected final void begin() {
190     if (interruptor == null) {
191         interruptor = new Interruptible() {
192             public void interrupt() {
193             AbstractSelector.this.wakeup();
194             }};
195     }
196     AbstractInterruptibleChannel.blockedOn(interruptor);
197     if (Thread.currentThread().isInterrupted())
198         interruptor.interrupt();
199     }
200
201     /**
202      * Marks the end of an I/O operation that might block indefinitely.
203      *
204      * <p> This method should be invoked in tandem with the {@link #end end}
205      * method, using a <tt>try</tt>&nbsp;...&nbsp;<tt>finally</tt> block as
206      * shown <a HREF="#be">above</a>, in order to implement interruption for
207      * this selector. </p>
208      */

209     protected final void end() {
210     AbstractInterruptibleChannel.blockedOn(null);
211     }
212
213 }
214
Popular Tags