1 /* 2 * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.nio.ch; 27 28 import java.lang.invoke.ConstantBootstraps; 29 import java.lang.invoke.MethodHandles; 30 import java.lang.invoke.VarHandle; 31 import java.nio.channels.CancelledKeyException; 32 import java.nio.channels.SelectableChannel; 33 import java.nio.channels.SelectionKey; 34 import java.nio.channels.Selector; 35 import java.nio.channels.spi.AbstractSelectionKey; 36 37 38 /** 39 * An implementation of SelectionKey. 40 */ 41 42 public final class SelectionKeyImpl 43 extends AbstractSelectionKey 44 { 45 private static final VarHandle INTERESTOPS = 46 ConstantBootstraps.fieldVarHandle( 47 MethodHandles.lookup(), 48 "interestOps", 49 VarHandle.class, 50 SelectionKeyImpl.class, int.class); 51 52 private final SelChImpl channel; 53 private final SelectorImpl selector; 54 55 private volatile int interestOps; 56 private volatile int readyOps; 57 58 // registered events in kernel, used by some Selector implementations 59 private int registeredEvents; 60 61 // registered events need to be reset, used by some Selector implementations 62 private volatile boolean reset; 63 64 // index of key in pollfd array, used by some Selector implementations 65 private int index; 66 SelectionKeyImpl(SelChImpl ch, SelectorImpl sel)67 SelectionKeyImpl(SelChImpl ch, SelectorImpl sel) { 68 channel = ch; 69 selector = sel; 70 } 71 ensureValid()72 private void ensureValid() { 73 if (!isValid()) 74 throw new CancelledKeyException(); 75 } 76 getFDVal()77 int getFDVal() { 78 return channel.getFDVal(); 79 } 80 81 @Override channel()82 public SelectableChannel channel() { 83 return (SelectableChannel)channel; 84 } 85 86 @Override selector()87 public Selector selector() { 88 return selector; 89 } 90 91 @Override interestOps()92 public int interestOps() { 93 ensureValid(); 94 return interestOps; 95 } 96 97 @Override interestOps(int ops)98 public SelectionKey interestOps(int ops) { 99 ensureValid(); 100 if ((ops & ~channel().validOps()) != 0) 101 throw new IllegalArgumentException(); 102 int oldOps = (int) INTERESTOPS.getAndSet(this, ops); 103 if (ops != oldOps) { 104 selector.setEventOps(this); 105 } 106 return this; 107 } 108 109 @Override interestOpsOr(int ops)110 public int interestOpsOr(int ops) { 111 ensureValid(); 112 if ((ops & ~channel().validOps()) != 0) 113 throw new IllegalArgumentException(); 114 int oldVal = (int) INTERESTOPS.getAndBitwiseOr(this, ops); 115 if (oldVal != (oldVal | ops)) { 116 selector.setEventOps(this); 117 } 118 return oldVal; 119 } 120 121 @Override interestOpsAnd(int ops)122 public int interestOpsAnd(int ops) { 123 ensureValid(); 124 int oldVal = (int) INTERESTOPS.getAndBitwiseAnd(this, ops); 125 if (oldVal != (oldVal & ops)) { 126 selector.setEventOps(this); 127 } 128 return oldVal; 129 } 130 131 @Override readyOps()132 public int readyOps() { 133 ensureValid(); 134 return readyOps; 135 } 136 137 // The nio versions of these operations do not care if a key 138 // has been invalidated. They are for internal use by nio code. 139 nioReadyOps(int ops)140 public void nioReadyOps(int ops) { 141 readyOps = ops; 142 } 143 nioReadyOps()144 public int nioReadyOps() { 145 return readyOps; 146 } 147 nioInterestOps(int ops)148 public SelectionKey nioInterestOps(int ops) { 149 if ((ops & ~channel().validOps()) != 0) 150 throw new IllegalArgumentException(); 151 interestOps = ops; 152 selector.setEventOps(this); 153 return this; 154 } 155 nioInterestOps()156 public int nioInterestOps() { 157 return interestOps; 158 } 159 translateInterestOps()160 int translateInterestOps() { 161 return channel.translateInterestOps(interestOps); 162 } 163 translateAndSetReadyOps(int ops)164 boolean translateAndSetReadyOps(int ops) { 165 return channel.translateAndSetReadyOps(ops, this); 166 } 167 translateAndUpdateReadyOps(int ops)168 boolean translateAndUpdateReadyOps(int ops) { 169 return channel.translateAndUpdateReadyOps(ops, this); 170 } 171 registeredEvents(int events)172 void registeredEvents(int events) { 173 // assert Thread.holdsLock(selector); 174 this.registeredEvents = events; 175 } 176 registeredEvents()177 int registeredEvents() { 178 // assert Thread.holdsLock(selector); 179 return registeredEvents; 180 } 181 getIndex()182 int getIndex() { 183 return index; 184 } 185 setIndex(int i)186 void setIndex(int i) { 187 index = i; 188 } 189 190 /** 191 * Sets the reset flag, re-queues the key, and wakeups up the Selector 192 */ reset()193 void reset() { 194 reset = true; 195 selector.setEventOps(this); 196 selector.wakeup(); 197 } 198 199 /** 200 * Clears the reset flag, returning the previous value of the flag 201 */ getAndClearReset()202 boolean getAndClearReset() { 203 assert Thread.holdsLock(selector); 204 boolean r = reset; 205 if (r) 206 reset = false; 207 return r; 208 } 209 210 @Override toString()211 public String toString() { 212 StringBuilder sb = new StringBuilder(); 213 sb.append("channel=") 214 .append(channel) 215 .append(", selector=") 216 .append(selector); 217 if (isValid()) { 218 sb.append(", interestOps=") 219 .append(interestOps) 220 .append(", readyOps=") 221 .append(readyOps); 222 } else { 223 sb.append(", invalid"); 224 } 225 return sb.toString(); 226 } 227 228 // used by Selector implementations to record when the key was selected 229 int lastPolled; 230 } 231