API Overview API Index Package Overview Direct link to this page
JDK 1.6
  java.nio.channels.spi. AbstractSelectableChannel View Javadoc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277

/*
 * @(#)AbstractSelectableChannel.java	1.26 05/11/17
 *
 * Copyright 2006 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.*;


/**
 * Base implementation class for selectable channels.
 *
 * <p> This class defines methods that handle the mechanics of channel
 * registration, deregistration, and closing.  It maintains the current
 * blocking mode of this channel as well as its current set of selection keys.
 * It performs all of the synchronization required to implement the {@link
 * java.nio.channels.SelectableChannel} specification.  Implementations of the
 * abstract protected methods defined in this class need not synchronize
 * against other threads that might be engaged in the same operations.  </p>
 *
 *
 * @author Mark Reinhold
 * @author Mike McCloskey
 * @author JSR-51 Expert Group
 * @version 1.26, 05/11/17
 * @since 1.4
 */

public abstract class AbstractSelectableChannel extends SelectableChannel
{

    // The provider that created this channel
    private final SelectorProvider provider;

    // Keys that have been created by registering this channel with selectors.
    // They are saved because if this channel is closed the keys must be
    // deregistered.  Protected by keyLock.
    //
    private SelectionKey[] keys = null;
    private int keyCount = 0;

    // Lock for key set and count
    private final Object keyLock = new Object();

    // Lock for registration and configureBlocking operations
    private final Object regLock = new Object();

    // Blocking mode, protected by regLock
    boolean blocking = true;

    /**
     * Initializes a new instance of this class.
     */
    protected AbstractSelectableChannel(SelectorProvider provider) {
	this.provider = provider;
    }

    /**
     * Returns the provider that created this channel.
     *
     * @return  The provider that created this channel
     */
    public final SelectorProvider provider() {
	return provider;
    }


    // -- Utility methods for the key set --

    private void addKey(SelectionKey k) {
	synchronized (keyLock) {
	    int i = 0;
	    if ((keys != null) && (keyCount < keys.length)) {
		// Find empty element of key array
		for (i = 0; i < keys.length; i++)
		    if (keys[i] == null)
			break;
	    } else if (keys == null) {
                keys =  new SelectionKey[3];
            } else {
		// Grow key array
		int n = keys.length * 2;
		SelectionKey[] ks =  new SelectionKey[n];
		for (i = 0; i < keys.length; i++)
		    ks[i] = keys[i];
		keys = ks;
		i = keyCount;
	    }
	    keys[i] = k;
	    keyCount++;
	}
    }

    private SelectionKey findKey(Selector sel) {
	synchronized (keyLock) {
            if (keys == null)
                return null;
	    for (int i = 0; i < keys.length; i++)
                if ((keys[i] != null) && (keys[i].selector() == sel))
                    return keys[i];
	    return null;
	}
    }

    void removeKey(SelectionKey k) {			// package-private
	synchronized (keyLock) {
	    for (int i = 0; i < keys.length; i++)
		if (keys[i] == k) {
		    keys[i] = null;
		    keyCount--;
		}
	    ((AbstractSelectionKey)k).invalidate();
	}
    }

    private boolean haveValidKeys() {
	synchronized (keyLock) {
	    if (keyCount == 0)
		return false;
	    for (int i = 0; i < keys.length; i++) {
		if ((keys[i] != null) && keys[i].isValid())
		    return true;
	    }
	    return false;
	}
    }


    // -- Registration --

    public final boolean isRegistered() {
	synchronized (keyLock) {
	    return keyCount != 0;
	}
    }

    public final SelectionKey keyFor(Selector sel) {
	return findKey(sel);
    }

    /**
     * Registers this channel with the given selector, returning a selection key.
     *
     * <p>  This method first verifies that this channel is open and that the
     * given initial interest set is valid.
     *
     * <p> If this channel is already registered with the given selector then
     * the selection key representing that registration is returned after
     * setting its interest set to the given value.
     *
     * <p> Otherwise this channel has not yet been registered with the given
     * selector, so the {@link AbstractSelector#register register} method of
     * the selector is invoked while holding the appropriate locks.  The
     * resulting key is added to this channel's key set before being returned.
     * </p>
     */
    public final SelectionKey register(Selector sel, int ops,
				       Object att)
	throws ClosedChannelException
    {
	if (!isOpen())
	    throw new ClosedChannelException();
	if ((ops & ~validOps()) != 0)
	    throw new IllegalArgumentException();
	synchronized (regLock) {
	    if (blocking)
		throw new IllegalBlockingModeException();
	    SelectionKey k = findKey(sel);
            if (k != null) {
                k.interestOps(ops);
		k.attach(att);
            }
	    if (k == null) {
		// New registration
		k = ((AbstractSelector)sel).register(this, ops, att);
		addKey(k);
	    }
            return k;
        }
    }


    // -- Closing --

    /**
     * Closes this channel.
     *
     * <p> This method, which is specified in the {@link
     * AbstractInterruptibleChannel} class and is invoked by the {@link
     * java.nio.channels.Channel#close close} method, in turn invokes the
     * {@link #implCloseSelectableChannel implCloseSelectableChannel} method in
     * order to perform the actual work of closing this channel.  It then
     * cancels all of this channel's keys.  </p>
     */
    protected final void implCloseChannel() throws IOException {
	implCloseSelectableChannel();
	synchronized (keyLock) {
            int count = (keys == null) ? 0 : keys.length;
	    for (int i = 0; i < count; i++) {
		SelectionKey k = keys[i];
		if (k != null)
		    k.cancel();
	    }
	}
    }

    /**
     * Closes this selectable channel.
     *
     * <p> This method is invoked by the {@link java.nio.channels.Channel#close
     * close} method in order to perform the actual work of closing the
     * channel.  This method is only invoked if the channel 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 an I/O operation upon this channel to return
     * immediately, either by throwing an exception or by returning normally.
     * </p>
     */
    protected abstract void implCloseSelectableChannel() throws IOException;


    // -- Blocking --

    public final boolean isBlocking() {
	synchronized (regLock) {
	    return blocking;
	}
    }

    public final Object blockingLock() {
	return regLock;
    }

    /**
     * Adjusts this channel's blocking mode.
     *
     * <p> If the given blocking mode is different from the current blocking
     * mode then this method invokes the {@link #implConfigureBlocking
     * implConfigureBlocking} method, while holding the appropriate locks, in
     * order to change the mode.  </p>
     */
    public final SelectableChannel configureBlocking(boolean block)
	throws IOException
    {
        if (!isOpen())
            throw new ClosedChannelException();
	synchronized (regLock) {
	    if (blocking == block)
		return this;
	    if (block && haveValidKeys())
		throw new IllegalBlockingModeException();
	    implConfigureBlocking(block);
	    blocking = block;
	}
	return this;
    }

    /**
     * Adjusts this channel's blocking mode.
     *
     * <p> This method is invoked by the {@link #configureBlocking
     * configureBlocking} method in order to perform the actual work of
     * changing the blocking mode.  This method is only invoked if the new mode
     * is different from the current mode.  </p>
     *
     * @throws IOException
     *         If an I/O error occurs
     */
    protected abstract void implConfigureBlocking(boolean block)
	throws IOException;

}

Generated By: JavaOnTracks Doclet 0.1.4     ©Thibaut Colar