1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package java.nio.channels.spi; 19 20import java.io.IOException; 21import java.nio.channels.SelectionKey; 22import java.nio.channels.Selector; 23import java.util.HashSet; 24import java.util.Set; 25import java.util.concurrent.atomic.AtomicBoolean; 26 27/** 28 * {@code AbstractSelector} is the base implementation class for selectors. 29 * It realizes the interruption of selection by {@code begin} and 30 * {@code end}. It also holds the cancellation and the deletion of the key 31 * set. 32 */ 33public abstract class AbstractSelector extends Selector { 34 private final AtomicBoolean isOpen = new AtomicBoolean(true); 35 36 private SelectorProvider provider = null; 37 38 private final Set<SelectionKey> cancelledKeysSet = new HashSet<SelectionKey>(); 39 40 private final Runnable wakeupRunnable = new Runnable() { 41 @Override public void run() { 42 wakeup(); 43 } 44 }; 45 46 protected AbstractSelector(SelectorProvider selectorProvider) { 47 provider = selectorProvider; 48 } 49 50 /** 51 * Closes this selector. This method does nothing if this selector is 52 * already closed. The actual closing must be implemented by subclasses in 53 * {@code implCloseSelector()}. 54 */ 55 @Override 56 public final void close() throws IOException { 57 if (isOpen.getAndSet(false)) { 58 implCloseSelector(); 59 } 60 } 61 62 /** 63 * Implements the closing of this channel. 64 */ 65 protected abstract void implCloseSelector() throws IOException; 66 67 /** 68 * Returns true if this selector is open. 69 */ 70 @Override 71 public final boolean isOpen() { 72 return isOpen.get(); 73 } 74 75 /** 76 * Returns this selector's provider. 77 */ 78 @Override 79 public final SelectorProvider provider() { 80 return provider; 81 } 82 83 /** 84 * Returns this channel's set of canceled selection keys. 85 */ 86 protected final Set<SelectionKey> cancelledKeys() { 87 return cancelledKeysSet; 88 } 89 90 /** 91 * Registers {@code channel} with this selector. 92 * 93 * @param operations the {@link SelectionKey interest set} of {@code 94 * channel}. 95 * @param attachment the attachment for the selection key. 96 * @return the key related to the channel and this selector. 97 */ 98 protected abstract SelectionKey register(AbstractSelectableChannel channel, 99 int operations, Object attachment); 100 101 /** 102 * Deletes the key from the channel's key set. 103 */ 104 protected final void deregister(AbstractSelectionKey key) { 105 ((AbstractSelectableChannel) key.channel()).deregister(key); 106 key.isValid = false; 107 } 108 109 /** 110 * Indicates the beginning of a code section that includes an I/O operation 111 * that is potentially blocking. After this operation, the application 112 * should invoke the corresponding {@code end(boolean)} method. 113 */ 114 protected final void begin() { 115 Thread.currentThread().pushInterruptAction$(wakeupRunnable); 116 } 117 118 /** 119 * Indicates the end of a code section that has been started with 120 * {@code begin()} and that includes a potentially blocking I/O operation. 121 */ 122 protected final void end() { 123 Thread.currentThread().popInterruptAction$(wakeupRunnable); 124 } 125 126 void cancel(SelectionKey key) { 127 synchronized (cancelledKeysSet) { 128 cancelledKeysSet.add(key); 129 } 130 } 131} 132