View Javadoc
1   /*
2    * junixsocket
3    *
4    * Copyright 2009-2026 Christian Kohlschütter
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.newsclub.net.unix;
19  
20  import java.nio.channels.SelectableChannel;
21  import java.nio.channels.SelectionKey;
22  import java.nio.channels.Selector;
23  import java.nio.channels.spi.AbstractSelectableChannel;
24  import java.util.concurrent.atomic.AtomicBoolean;
25  import java.util.concurrent.atomic.AtomicInteger;
26  
27  import com.kohlschutter.annotations.compiletime.SuppressFBWarnings;
28  
29  final class AFSelectionKey extends SelectionKey {
30    private static final int OP_INVALID = 1 << 7; // custom
31    private final AFSelector sel;
32    private final AFSocketCore core;
33    private final AtomicInteger ops = new AtomicInteger();
34    private final AtomicInteger opsReady = new AtomicInteger(0);
35    private final SelectableChannel chann;
36    private final AtomicBoolean cancelled = new AtomicBoolean();
37  
38    AFSelectionKey(AFSelector selector, AbstractSelectableChannel ch, int ops, Object att) {
39      super();
40      this.chann = ch;
41      this.sel = selector;
42      this.ops.set(ops); // FIXME check
43  
44      if (ch instanceof AFDatagramChannel<?>) {
45        this.core = ((AFDatagramChannel<?>) ch).getAFCore();
46      } else if (ch instanceof AFSocketChannel<?>) {
47        this.core = ((AFSocketChannel<?>) ch).getAFCore();
48      } else if (ch instanceof AFServerSocketChannel<?>) {
49        this.core = ((AFServerSocketChannel<?>) ch).getAFCore();
50      } else {
51        throw new UnsupportedOperationException("Unsupported channel: " + ch);
52      }
53  
54      attach(att);
55    }
56  
57    @Override
58    @SuppressFBWarnings("EI_EXPOSE_REP")
59    public SelectableChannel channel() {
60      return chann;
61    }
62  
63    @Override
64    @SuppressFBWarnings("EI_EXPOSE_REP")
65    public Selector selector() {
66      return sel;
67    }
68  
69    @Override
70    public boolean isValid() {
71      return !hasOpInvalid() && !cancelled.get() && chann.isOpen() && sel.isOpen();
72    }
73  
74    boolean isCancelled() {
75      return cancelled.get();
76    }
77  
78    boolean hasOpInvalid() {
79      return (opsReady.get() & OP_INVALID) != 0;
80    }
81  
82    boolean isSelected() {
83      return readyOps() != 0;
84    }
85  
86    @Override
87    public void cancel() {
88      sel.remove(this);
89      cancelNoRemove();
90    }
91  
92    void cancelNoRemove() {
93      if (!cancelled.compareAndSet(false, true) || !chann.isOpen()) {
94        return;
95      }
96  
97      cancel1();
98    }
99  
100   private void cancel1() {
101     // FIXME
102   }
103 
104   @Override
105   public int interestOps() {
106     return ops.get();
107   }
108 
109   @Override
110   public SelectionKey interestOps(int interestOps) {
111     this.ops.set(interestOps); // FIXME check
112     return this;
113   }
114 
115   @Override
116   public int readyOps() {
117     return opsReady.get() & ~OP_INVALID;
118   }
119 
120   AFSocketCore getAFCore() {
121     return core;
122   }
123 
124   void setOpsReady(int opsReady) {
125     this.opsReady.set(opsReady);
126   }
127 
128   @Override
129   public String toString() {
130     return super.toString() + "[" + readyOps() + ";valid=" + isValid() + ";channel=" + channel()
131         + "]";
132   }
133 }