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 }