1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  this work for additional information regarding copyright ownership.
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  (the "License"); you may not use this file except in compliance with
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  the License.  You may obtain a copy of the License at
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  See the License for the specific language governing permissions and
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  limitations under the License.
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.nio.channels.spi;
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException;
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.CancelledKeyException;
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.ClosedChannelException;
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.IllegalBlockingModeException;
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.IllegalSelectorException;
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.SelectableChannel;
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.SelectionKey;
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.Selector;
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.ArrayList;
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.List;
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code AbstractSelectableChannel} is the base implementation class for
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * selectable channels. It declares methods for registering, unregistering and
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * closing selectable channels. It is thread-safe.
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic abstract class AbstractSelectableChannel extends SelectableChannel {
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private final SelectorProvider provider;
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /*
41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The collection of key.
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private List<SelectionKey> keyList = new ArrayList<SelectionKey>();
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
455e23b687ef8b3c696d54d1880b454942875665b7Elliott Hughes    private final Object blockingLock = new Object();
46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    boolean isBlocking = true;
48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs a new {@code AbstractSelectableChannel}.
51f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param selectorProvider
53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the selector provider that creates this channel.
54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected AbstractSelectableChannel(SelectorProvider selectorProvider) {
56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        provider = selectorProvider;
57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the selector provider that has created this channel.
61f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @see java.nio.channels.SelectableChannel#provider()
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return this channel's selector provider.
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
65eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson    @Override
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final SelectorProvider provider() {
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return provider;
68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Indicates whether this channel is registered with one or more selectors.
72eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson     *
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if this channel is registered with a selector,
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         {@code false} otherwise.
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
76eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson    @Override
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    synchronized public final boolean isRegistered() {
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return !keyList.isEmpty();
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets this channel's selection key for the specified selector.
83eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson     *
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param selector
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the selector with which this channel has been registered.
86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the selection key for the channel or {@code null} if this channel
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         has not been registered with {@code selector}.
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
89eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson    @Override
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    synchronized public final SelectionKey keyFor(Selector selector) {
91220c0af1763283b75617226efe3919c3e3b044c8Elliott Hughes        for (SelectionKey key : keyList) {
92b46dab348e2007bc08abaf7ecae34d89a2474e50Elliott Hughes            if (key != null && key.selector() == selector) {
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return key;
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return null;
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Registers this channel with the specified selector for the specified
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * interest set. If the channel is already registered with the selector, the
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@link SelectionKey interest set} is updated to {@code interestSet} and
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the corresponding selection key is returned. If the channel is not yet
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * registered, this method calls the {@code register} method of
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code selector} and adds the selection key to this channel's key set.
106f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param selector
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the selector with which to register this channel.
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param interestSet
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            this channel's {@link SelectionKey interest set}.
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param attachment
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the object to attach, can be {@code null}.
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the selection key for this registration.
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws CancelledKeyException
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this channel is registered but its key has been canceled.
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws ClosedChannelException
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this channel is closed.
118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if {@code interestSet} is not supported by this channel.
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalBlockingModeException
121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this channel is in blocking mode.
122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalSelectorException
123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this channel does not have the same provider as the given
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             selector.
125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
126eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson    @Override
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final SelectionKey register(Selector selector, int interestSet,
128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Object attachment) throws ClosedChannelException {
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!isOpen()) {
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new ClosedChannelException();
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!((interestSet & ~validOps()) == 0)) {
133cff1616012dc0d56c2da9af2b9b1183e76c7e044Elliott Hughes            throw new IllegalArgumentException("no valid ops in interest set: " + interestSet);
134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (blockingLock) {
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isBlocking) {
138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                throw new IllegalBlockingModeException();
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!selector.isOpen()) {
141b46dab348e2007bc08abaf7ecae34d89a2474e50Elliott Hughes                if (interestSet == 0) {
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // throw ISE exactly to keep consistency
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    throw new IllegalSelectorException();
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // throw NPE exactly to keep consistency
146c2d0a1f1bd2c6414c29dd44fe240dcf1f45e59b9Elliott Hughes                throw new NullPointerException("selector not open");
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            SelectionKey key = keyFor(selector);
149b46dab348e2007bc08abaf7ecae34d89a2474e50Elliott Hughes            if (key == null) {
150b46dab348e2007bc08abaf7ecae34d89a2474e50Elliott Hughes                key = ((AbstractSelector) selector).register(this, interestSet, attachment);
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                keyList.add(key);
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (!key.isValid()) {
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    throw new CancelledKeyException();
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                key.interestOps(interestSet);
157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                key.attach(attachment);
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return key;
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Implements the channel closing behavior. Calls
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code implCloseSelectableChannel()} first, then loops through the list
166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * of selection keys and cancels them, which unregisters this channel from
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * all selectors it is registered with.
168f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if a problem occurs while closing the channel.
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
172eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson    @Override
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    synchronized protected final void implCloseChannel() throws IOException {
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        implCloseSelectableChannel();
175220c0af1763283b75617226efe3919c3e3b044c8Elliott Hughes        for (SelectionKey key : keyList) {
176b46dab348e2007bc08abaf7ecae34d89a2474e50Elliott Hughes            if (key != null) {
177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                key.cancel();
178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Implements the closing function of the SelectableChannel. This method is
184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * called from {@code implCloseChannel()}.
185f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an I/O exception occurs.
188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected abstract void implCloseSelectableChannel() throws IOException;
190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Indicates whether this channel is in blocking mode.
193eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson     *
194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if this channel is blocking, {@code false}
195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         otherwise.
196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
197eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson    @Override
198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final boolean isBlocking() {
199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (blockingLock) {
200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return isBlocking;
201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets the object used for the synchronization of {@code register} and
206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code configureBlocking}.
207eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson     *
208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the synchronization object.
209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
210eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson    @Override
211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final Object blockingLock() {
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return blockingLock;
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Sets the blocking mode of this channel. A call to this method blocks if
217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * other calls to this method or to {@code register} are executing. The
218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * actual setting of the mode is done by calling
219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * {@code implConfigureBlocking(boolean)}.
220f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
221eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson     * @see java.nio.channels.SelectableChannel#configureBlocking(boolean)
222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param blockingMode
223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            {@code true} for setting this channel's mode to blocking,
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            {@code false} to set it to non-blocking.
225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return this channel.
226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws ClosedChannelException
227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if this channel is closed.
228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalBlockingModeException
229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if {@code block} is {@code true} and this channel has been
230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             registered with at least one selector.
231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an I/O error occurs.
233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
234eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson    @Override
2354e4000ed98f9056639fba0713a3fd3caacf9746cElliott Hughes    public final SelectableChannel configureBlocking(boolean blockingMode) throws IOException {
236220c0af1763283b75617226efe3919c3e3b044c8Elliott Hughes        if (!isOpen()) {
237220c0af1763283b75617226efe3919c3e3b044c8Elliott Hughes            throw new ClosedChannelException();
238220c0af1763283b75617226efe3919c3e3b044c8Elliott Hughes        }
239220c0af1763283b75617226efe3919c3e3b044c8Elliott Hughes        synchronized (blockingLock) {
240220c0af1763283b75617226efe3919c3e3b044c8Elliott Hughes            if (isBlocking == blockingMode) {
241220c0af1763283b75617226efe3919c3e3b044c8Elliott Hughes                return this;
242220c0af1763283b75617226efe3919c3e3b044c8Elliott Hughes            }
243220c0af1763283b75617226efe3919c3e3b044c8Elliott Hughes            if (blockingMode && containsValidKeys()) {
244220c0af1763283b75617226efe3919c3e3b044c8Elliott Hughes                throw new IllegalBlockingModeException();
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
246220c0af1763283b75617226efe3919c3e3b044c8Elliott Hughes            implConfigureBlocking(blockingMode);
247220c0af1763283b75617226efe3919c3e3b044c8Elliott Hughes            isBlocking = blockingMode;
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
249220c0af1763283b75617226efe3919c3e3b044c8Elliott Hughes        return this;
250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
253a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes     * Implements the configuration of blocking/non-blocking mode.
254f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
255a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes     * @param blocking true for blocking, false for non-blocking.
256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an I/O error occurs.
258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
259a3b57e9cb41fb00ac607cd330fa73270b564b66cElliott Hughes    protected abstract void implConfigureBlocking(boolean blocking) throws IOException;
260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /*
262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * package private for deregister method in AbstractSelector.
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    synchronized void deregister(SelectionKey k) {
265b46dab348e2007bc08abaf7ecae34d89a2474e50Elliott Hughes        if (keyList != null) {
266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            keyList.remove(k);
267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
270eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson    /**
271eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson     * Returns true if the keyList contains at least 1 valid key and false
272eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson     * otherwise.
273eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson     */
274eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson    private synchronized boolean containsValidKeys() {
275220c0af1763283b75617226efe3919c3e3b044c8Elliott Hughes        for (SelectionKey key : keyList) {
276eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson            if (key != null && key.isValid()) {
277eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson                return true;
278eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson            }
279eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson        }
280eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson        return false;
281eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson    }
282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
283