1 /*
2  * Copyright (c) 2000, 2018, 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     // index of key in pollfd array, used by some Selector implementations
62     private int index;
63 
SelectionKeyImpl(SelChImpl ch, SelectorImpl sel)64     SelectionKeyImpl(SelChImpl ch, SelectorImpl sel) {
65         channel = ch;
66         selector = sel;
67     }
68 
ensureValid()69     private void ensureValid() {
70         if (!isValid())
71             throw new CancelledKeyException();
72     }
73 
getFDVal()74     int getFDVal() {
75         return channel.getFDVal();
76     }
77 
78     @Override
channel()79     public SelectableChannel channel() {
80         return (SelectableChannel)channel;
81     }
82 
83     @Override
selector()84     public Selector selector() {
85         return selector;
86     }
87 
88     @Override
interestOps()89     public int interestOps() {
90         ensureValid();
91         return interestOps;
92     }
93 
94     @Override
interestOps(int ops)95     public SelectionKey interestOps(int ops) {
96         ensureValid();
97         if ((ops & ~channel().validOps()) != 0)
98             throw new IllegalArgumentException();
99         int oldOps = (int) INTERESTOPS.getAndSet(this, ops);
100         if (ops != oldOps) {
101             selector.setEventOps(this);
102         }
103         return this;
104     }
105 
106     @Override
interestOpsOr(int ops)107     public int interestOpsOr(int ops) {
108         ensureValid();
109         if ((ops & ~channel().validOps()) != 0)
110             throw new IllegalArgumentException();
111         int oldVal = (int) INTERESTOPS.getAndBitwiseOr(this, ops);
112         if (oldVal != (oldVal | ops)) {
113             selector.setEventOps(this);
114         }
115         return oldVal;
116     }
117 
118     @Override
interestOpsAnd(int ops)119     public int interestOpsAnd(int ops) {
120         ensureValid();
121         int oldVal = (int) INTERESTOPS.getAndBitwiseAnd(this, ops);
122         if (oldVal != (oldVal & ops)) {
123             selector.setEventOps(this);
124         }
125         return oldVal;
126     }
127 
128     @Override
readyOps()129     public int readyOps() {
130         ensureValid();
131         return readyOps;
132     }
133 
134     // The nio versions of these operations do not care if a key
135     // has been invalidated. They are for internal use by nio code.
136 
nioReadyOps(int ops)137     public void nioReadyOps(int ops) {
138         readyOps = ops;
139     }
140 
nioReadyOps()141     public int nioReadyOps() {
142         return readyOps;
143     }
144 
nioInterestOps(int ops)145     public SelectionKey nioInterestOps(int ops) {
146         if ((ops & ~channel().validOps()) != 0)
147             throw new IllegalArgumentException();
148         interestOps = ops;
149         selector.setEventOps(this);
150         return this;
151     }
152 
nioInterestOps()153     public int nioInterestOps() {
154         return interestOps;
155     }
156 
translateInterestOps()157     int translateInterestOps() {
158         return channel.translateInterestOps(interestOps);
159     }
160 
translateAndSetReadyOps(int ops)161     boolean translateAndSetReadyOps(int ops) {
162         return channel.translateAndSetReadyOps(ops, this);
163     }
164 
translateAndUpdateReadyOps(int ops)165     boolean translateAndUpdateReadyOps(int ops) {
166         return channel.translateAndUpdateReadyOps(ops, this);
167     }
168 
registeredEvents(int events)169     void registeredEvents(int events) {
170         // assert Thread.holdsLock(selector);
171         this.registeredEvents = events;
172     }
173 
registeredEvents()174     int registeredEvents() {
175         // assert Thread.holdsLock(selector);
176         return registeredEvents;
177     }
178 
getIndex()179     int getIndex() {
180         return index;
181     }
182 
setIndex(int i)183     void setIndex(int i) {
184         index = i;
185     }
186 
187     @Override
toString()188     public String toString() {
189         StringBuilder sb = new StringBuilder();
190         sb.append("channel=")
191           .append(channel)
192           .append(", selector=")
193           .append(selector);
194         if (isValid()) {
195             sb.append(", interestOps=")
196               .append(interestOps)
197               .append(", readyOps=")
198               .append(readyOps);
199         } else {
200             sb.append(", invalid");
201         }
202         return sb.toString();
203     }
204 
205     // used by Selector implementations to record when the key was selected
206     int lastPolled;
207 }
208