View Javadoc
1   /*
2    * Copyright 2026 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License, version 2.0 (the
5    * "License"); you may not use this file except in compliance with the License. You may obtain a
6    * 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 distributed under the License
11   * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12   * or implied. See the License for the specific language governing permissions and limitations under
13   * the License.
14   */
15  
16  package io.netty.handler.codec.http2;
17  
18  import java.util.concurrent.atomic.AtomicInteger;
19  
20  /**
21   * Utility methods for creating {@link Http2Connection.PropertyKey}s.
22   */
23  final class Http2ConnectionPropertyKeys {
24  
25      /**
26       * Safe-guard against misuse: global keys are expected to be created rarely, typically once per use-case and
27       * stored in a {@code static} field, so there should never be a legitimate need for more than this many.
28       */
29      private static final int MAX_GLOBAL_KEYS = 8;
30  
31      private static final AtomicInteger nextIndex = new AtomicInteger();
32  
33      private Http2ConnectionPropertyKeys() { }
34  
35      /**
36       * Creates a new key that, unlike one returned by {@link Http2Connection#newKey()}, is not tied to a specific
37       * {@link Http2Connection} instance. The returned key can be used with the streams of any {@link Http2Connection},
38       * which makes it suitable for cases where a key needs to be shared, e.g. stored in a {@code static} field,
39       * across multiple connections, or created before a {@link Http2Connection} instance is even available.
40       * <p>
41       * Accessing a property that is associated with a key returned by this method is slower than accessing one
42       * associated with a key returned by {@link Http2Connection#newKey()}. Prefer the latter whenever a specific
43       * {@link Http2Connection} instance is available up-front.
44       */
45      static Http2Connection.PropertyKey newGlobalKey() {
46          int index = nextIndex.getAndIncrement();
47          if (index >= MAX_GLOBAL_KEYS) {
48              nextIndex.decrementAndGet();
49              throw new IllegalStateException("Only " + MAX_GLOBAL_KEYS + " global keys can be created");
50          }
51          return new GlobalPropertyKey(index);
52      }
53  
54      /**
55       * The number of keys created via {@link #newGlobalKey()} so far, which also doubles as the exclusive upper
56       * bound for {@link GlobalPropertyKey#index}.
57       */
58      static int keyCount() {
59          return nextIndex.get();
60      }
61  
62      /**
63       * Implementation of {@link Http2Connection.PropertyKey} that specifies the index position of the property and,
64       * unlike {@link DefaultHttp2Connection.DefaultPropertyKey}, is not tied to a specific {@link Http2Connection}.
65       */
66      static final class GlobalPropertyKey implements Http2Connection.PropertyKey {
67          final int index;
68  
69          private GlobalPropertyKey(int index) {
70              this.index = index;
71          }
72  
73          @Override
74          public boolean equals(Object o) {
75              if (!(o instanceof GlobalPropertyKey)) {
76                  return false;
77              }
78              GlobalPropertyKey that = (GlobalPropertyKey) o;
79              return index == that.index;
80          }
81  
82          @Override
83          public int hashCode() {
84              return index;
85          }
86      }
87  }