View Javadoc
1   /*
2    * Copyright 2024 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.channel.nio;
17  
18  import io.netty.channel.IoOps;
19  
20  import java.nio.channels.SelectionKey;
21  
22  /**
23   * Implementation of {@link IoOps} for
24   * that is used by {@link NioIoHandler} and so for NIO based transports.
25   */
26  public final class NioIoOps implements IoOps {
27      /**
28       * Interested in NO IO events.
29       */
30      public static final NioIoOps NONE = new NioIoOps(0);
31  
32      /**
33       * Interested in IO events that should be handled by accepting new connections
34       */
35      public static final NioIoOps ACCEPT = new NioIoOps(SelectionKey.OP_ACCEPT);
36  
37      /**
38       * Interested in IO events which should be handled by finish pending connect operations
39       */
40      public static final NioIoOps CONNECT = new NioIoOps(SelectionKey.OP_CONNECT);
41  
42      /**
43       * Interested in IO events which tell that the underlying channel is writable again.
44       */
45      public static final NioIoOps WRITE = new NioIoOps(SelectionKey.OP_WRITE);
46  
47      /**
48       * Interested in IO events which should be handled by reading data.
49       */
50      public static final NioIoOps READ = new NioIoOps(SelectionKey.OP_READ);
51  
52      /**
53       * Interested in IO events which should be either handled by reading or accepting.
54       */
55      public static final NioIoOps READ_AND_ACCEPT = new NioIoOps(SelectionKey.OP_READ | SelectionKey.OP_ACCEPT);
56  
57      /**
58       * Interested in IO events which should be either handled by reading or writing.
59       */
60      public static final NioIoOps READ_AND_WRITE = new NioIoOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE);
61  
62      // Just use an array to store often used values.
63      private static final NioIoEvent[] EVENTS;
64  
65      static {
66          NioIoOps all = new NioIoOps(
67                  NONE.value | ACCEPT.value | CONNECT.value | WRITE.value | READ.value);
68  
69          EVENTS = new NioIoEvent[all.value + 1];
70          addToArray(EVENTS, NONE);
71          addToArray(EVENTS, ACCEPT);
72          addToArray(EVENTS, CONNECT);
73          addToArray(EVENTS, WRITE);
74          addToArray(EVENTS, READ);
75          addToArray(EVENTS, READ_AND_ACCEPT);
76          addToArray(EVENTS, READ_AND_WRITE);
77          addToArray(EVENTS, all);
78      }
79  
80      private static void addToArray(NioIoEvent[] array, NioIoOps opt) {
81          array[opt.value] = new DefaultNioIoEvent(opt);
82      }
83  
84      final int value;
85  
86      private NioIoOps(int value) {
87          this.value = value;
88      }
89  
90      /**
91       * Returns {@code true} if this {@link NioIoOps} is a combination of the given {@link NioIoOps}.
92       * @param ops   the ops.
93       * @return      {@code true} if a combination of the given.
94       */
95      public boolean contains(NioIoOps ops) {
96          return isIncludedIn(ops.value);
97      }
98  
99      /**
100      * Return a {@link NioIoOps} which is a combination of the current and the given {@link NioIoOps}.
101      *
102      * @param ops   the {@link NioIoOps} that should be added to this one.
103      * @return      a {@link NioIoOps}.
104      */
105     public NioIoOps with(NioIoOps ops) {
106         if (contains(ops)) {
107             return this;
108         }
109         return valueOf(value | ops.value());
110     }
111 
112     /**
113      * Return a {@link NioIoOps} which is not a combination of the current and the given {@link NioIoOps}.
114      *
115      * @param ops   the {@link NioIoOps} that should be remove from this one.
116      * @return      a {@link NioIoOps}.
117      */
118     public NioIoOps without(NioIoOps ops) {
119         if (!contains(ops)) {
120             return this;
121         }
122         return valueOf(value & ~ops.value());
123     }
124 
125     /**
126      * Returns the underlying ops value of the {@link NioIoOps}.
127      *
128      * @return value.
129      */
130     public int value() {
131         return value;
132     }
133 
134     @Override
135     public boolean equals(Object o) {
136         if (this == o) {
137             return true;
138         }
139         if (o == null || getClass() != o.getClass()) {
140             return false;
141         }
142         NioIoOps nioOps = (NioIoOps) o;
143         return value == nioOps.value;
144     }
145 
146     @Override
147     public int hashCode() {
148         return value;
149     }
150 
151     /**
152      * Returns a {@link NioIoOps} for the given value.
153      *
154      * @param   value the value
155      * @return  the {@link NioIoOps}.
156      */
157     public static NioIoOps valueOf(int value) {
158         return eventOf(value).ops();
159     }
160 
161     /**
162      * Returns {@code true} if this {@link NioIoOps} is <strong>included </strong> in the given {@code ops}.
163      *
164      * @param ops   the ops to check.
165      * @return      {@code true} if <strong>included</strong>, {@code false} otherwise.
166      */
167     public boolean isIncludedIn(int ops) {
168         return (ops & value) != 0;
169     }
170 
171     /**
172      * Returns {@code true} if this {@link NioIoOps} is <strong>not included</strong> in the given {@code ops}.
173      *
174      * @param ops   the ops to check.
175      * @return      {@code true} if <strong>not included</strong>, {@code false} otherwise.
176      */
177     public boolean isNotIncludedIn(int ops) {
178         return (ops & value) == 0;
179     }
180 
181     static NioIoEvent eventOf(int value) {
182         if (value > 0 && value < EVENTS.length) {
183             NioIoEvent event = EVENTS[value];
184             if (event != null) {
185                 return event;
186             }
187         }
188         return new DefaultNioIoEvent(new NioIoOps(value));
189     }
190 
191     private static final class DefaultNioIoEvent implements NioIoEvent {
192         private final NioIoOps ops;
193 
194         DefaultNioIoEvent(NioIoOps ops) {
195             this.ops = ops;
196         }
197 
198         @Override
199         public NioIoOps ops() {
200             return ops;
201         }
202 
203         @Override
204         public boolean equals(Object o) {
205             if (this == o) {
206                 return true;
207             }
208             if (o == null || getClass() != o.getClass()) {
209                 return false;
210             }
211             NioIoEvent event = (NioIoEvent) o;
212             return event.ops().equals(ops());
213         }
214 
215         @Override
216         public int hashCode() {
217             return ops().hashCode();
218         }
219     }
220 }