1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty5.util.concurrent;
17
18 import io.netty5.util.internal.PlatformDependent;
19
20 import java.util.Collections;
21 import java.util.IdentityHashMap;
22 import java.util.Set;
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 public class FastThreadLocal<V> {
44
45 private static final int variablesToRemoveIndex = InternalThreadLocalMap.nextVariableIndex();
46
47
48
49
50
51
52 public static void removeAll() {
53 InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.getIfSet();
54 if (threadLocalMap == null) {
55 return;
56 }
57
58 try {
59 Object v = threadLocalMap.indexedVariable(variablesToRemoveIndex);
60 if (v != null && v != InternalThreadLocalMap.UNSET) {
61 @SuppressWarnings("unchecked")
62 Set<FastThreadLocal<?>> variablesToRemove = (Set<FastThreadLocal<?>>) v;
63 FastThreadLocal<?>[] variablesToRemoveArray =
64 variablesToRemove.toArray(new FastThreadLocal[0]);
65 for (FastThreadLocal<?> tlv: variablesToRemoveArray) {
66 tlv.remove(threadLocalMap);
67 }
68 }
69 } finally {
70 InternalThreadLocalMap.remove();
71 }
72 }
73
74
75
76
77 public static int size() {
78 InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.getIfSet();
79 if (threadLocalMap == null) {
80 return 0;
81 } else {
82 return threadLocalMap.size();
83 }
84 }
85
86
87
88
89
90
91
92 public static void destroy() {
93 InternalThreadLocalMap.destroy();
94 }
95
96 @SuppressWarnings("unchecked")
97 private static void addToVariablesToRemove(InternalThreadLocalMap threadLocalMap, FastThreadLocal<?> variable) {
98 Object v = threadLocalMap.indexedVariable(variablesToRemoveIndex);
99 Set<FastThreadLocal<?>> variablesToRemove;
100 if (v == InternalThreadLocalMap.UNSET || v == null) {
101 variablesToRemove = Collections.newSetFromMap(new IdentityHashMap<>());
102 threadLocalMap.setIndexedVariable(variablesToRemoveIndex, variablesToRemove);
103 } else {
104 variablesToRemove = (Set<FastThreadLocal<?>>) v;
105 }
106
107 variablesToRemove.add(variable);
108 }
109
110 private static void removeFromVariablesToRemove(
111 InternalThreadLocalMap threadLocalMap, FastThreadLocal<?> variable) {
112
113 Object v = threadLocalMap.indexedVariable(variablesToRemoveIndex);
114
115 if (v == InternalThreadLocalMap.UNSET || v == null) {
116 return;
117 }
118
119 @SuppressWarnings("unchecked")
120 Set<FastThreadLocal<?>> variablesToRemove = (Set<FastThreadLocal<?>>) v;
121 variablesToRemove.remove(variable);
122 }
123
124 private final int index;
125
126 public FastThreadLocal() {
127 index = InternalThreadLocalMap.nextVariableIndex();
128 }
129
130
131
132
133 @SuppressWarnings("unchecked")
134 public final V get() {
135 InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.get();
136 Object v = threadLocalMap.indexedVariable(index);
137 if (v != InternalThreadLocalMap.UNSET) {
138 return (V) v;
139 }
140
141 return initialize(threadLocalMap);
142 }
143
144
145
146
147 @SuppressWarnings("unchecked")
148 public final V getIfExists() {
149 InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.getIfSet();
150 if (threadLocalMap != null) {
151 Object v = threadLocalMap.indexedVariable(index);
152 if (v != InternalThreadLocalMap.UNSET) {
153 return (V) v;
154 }
155 }
156 return null;
157 }
158
159 private V initialize(InternalThreadLocalMap threadLocalMap) {
160 V v = null;
161 try {
162 v = initialValue();
163 } catch (Exception e) {
164 PlatformDependent.throwException(e);
165 }
166
167 threadLocalMap.setIndexedVariable(index, v);
168 addToVariablesToRemove(threadLocalMap, this);
169 return v;
170 }
171
172
173
174
175 public final void set(V value) {
176 set(InternalThreadLocalMap.get(), value);
177 }
178
179
180
181
182 private void set(InternalThreadLocalMap threadLocalMap, V value) {
183 if (value != InternalThreadLocalMap.UNSET) {
184 setKnownNotUnset(threadLocalMap, value);
185 } else {
186 remove(threadLocalMap);
187 }
188 }
189
190
191
192
193 private void setKnownNotUnset(InternalThreadLocalMap threadLocalMap, V value) {
194 if (threadLocalMap.setIndexedVariable(index, value)) {
195 addToVariablesToRemove(threadLocalMap, this);
196 }
197 }
198
199
200
201
202 public final boolean isSet() {
203 return isSet(InternalThreadLocalMap.getIfSet());
204 }
205
206
207
208
209
210 private boolean isSet(InternalThreadLocalMap threadLocalMap) {
211 return threadLocalMap != null && threadLocalMap.isIndexedVariableSet(index);
212 }
213
214
215
216
217 public final void remove() {
218 remove(InternalThreadLocalMap.getIfSet());
219 }
220
221
222
223
224
225
226 @SuppressWarnings("unchecked")
227 private void remove(InternalThreadLocalMap threadLocalMap) {
228 if (threadLocalMap == null) {
229 return;
230 }
231
232 Object v = threadLocalMap.removeIndexedVariable(index);
233 removeFromVariablesToRemove(threadLocalMap, this);
234
235 if (v != InternalThreadLocalMap.UNSET) {
236 try {
237 onRemoval((V) v);
238 } catch (Exception e) {
239 PlatformDependent.throwException(e);
240 }
241 }
242 }
243
244
245
246
247 protected V initialValue() throws Exception {
248 return null;
249 }
250
251
252
253
254
255
256 protected void onRemoval(@SuppressWarnings("UnusedParameters") V value) throws Exception { }
257 }