/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package java.nio.channels.spi; import java.io.IOException; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.util.HashSet; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; /** * {@code AbstractSelector} is the base implementation class for selectors. * It realizes the interruption of selection by {@code begin} and * {@code end}. It also holds the cancellation and the deletion of the key * set. */ public abstract class AbstractSelector extends Selector { private final AtomicBoolean isOpen = new AtomicBoolean(true); private SelectorProvider provider = null; private final Set<SelectionKey> cancelledKeysSet = new HashSet<SelectionKey>(); private final Runnable wakeupRunnable = new Runnable() { @Override public void run() { wakeup(); } }; protected AbstractSelector(SelectorProvider selectorProvider) { provider = selectorProvider; } /** * Closes this selector. This method does nothing if this selector is * already closed. The actual closing must be implemented by subclasses in * {@code implCloseSelector()}. */ @Override public final void close() throws IOException { if (isOpen.getAndSet(false)) { implCloseSelector(); } } /** * Implements the closing of this channel. */ protected abstract void implCloseSelector() throws IOException; /** * Returns true if this selector is open. */ @Override public final boolean isOpen() { return isOpen.get(); } /** * Returns this selector's provider. */ @Override public final SelectorProvider provider() { return provider; } /** * Returns this channel's set of canceled selection keys. */ protected final Set<SelectionKey> cancelledKeys() { return cancelledKeysSet; } /** * Registers {@code channel} with this selector. * * @param operations the {@link SelectionKey interest set} of {@code * channel}. * @param attachment the attachment for the selection key. * @return the key related to the channel and this selector. */ protected abstract SelectionKey register(AbstractSelectableChannel channel, int operations, Object attachment); /** * Deletes the key from the channel's key set. */ protected final void deregister(AbstractSelectionKey key) { ((AbstractSelectableChannel) key.channel()).deregister(key); key.isValid = false; } /** * Indicates the beginning of a code section that includes an I/O operation * that is potentially blocking. After this operation, the application * should invoke the corresponding {@code end(boolean)} method. */ protected final void begin() { Thread.currentThread().pushInterruptAction$(wakeupRunnable); } /** * Indicates the end of a code section that has been started with * {@code begin()} and that includes a potentially blocking I/O operation. */ protected final void end() { Thread.currentThread().popInterruptAction$(wakeupRunnable); } void cancel(SelectionKey key) { synchronized (cancelledKeysSet) { cancelledKeysSet.add(key); } } }