Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
ThreadLocal.cs
Go to the documentation of this file.
4
5namespace System.Threading;
6
8[DebuggerDisplay("IsValueCreated={IsValueCreated}, Value={ValueForDebugDisplay}, Count={ValuesCountForDebugDisplay}")]
9public class ThreadLocal<T> : IDisposable
10{
11 private struct LinkedSlotVolatile
12 {
13 internal volatile LinkedSlot Value;
14 }
15
16 private sealed class LinkedSlot
17 {
18 internal volatile LinkedSlot _next;
19
20 internal volatile LinkedSlot _previous;
21
22 internal volatile LinkedSlotVolatile[] _slotArray;
23
24 internal T _value;
25
30 }
31
32 private sealed class IdManager
33 {
34 private int _nextIdToTry;
35
36 private volatile int _idsThatDoNotTrackAllValues;
37
38 private readonly List<byte> _ids = new List<byte>();
39
41
42 internal int GetId(bool trackAllValues)
43 {
44 lock (_ids)
45 {
46 int i;
47 for (i = _nextIdToTry; i < _ids.Count && _ids[i] != 0; i++)
48 {
49 }
50 byte b = (byte)(trackAllValues ? 1 : 2);
51 if (i == _ids.Count)
52 {
53 _ids.Add(b);
54 }
55 else
56 {
57 _ids[i] = b;
58 }
59 if (!trackAllValues)
60 {
62 }
63 _nextIdToTry = i + 1;
64 return i;
65 }
66 }
67
68 internal bool IdTracksAllValues(int id)
69 {
70 lock (_ids)
71 {
72 return _ids[id] == 1;
73 }
74 }
75
76 internal void ReturnId(int id, bool idTracksAllValues)
77 {
78 lock (_ids)
79 {
81 {
83 }
84 _ids[id] = 0;
85 if (id < _nextIdToTry)
86 {
87 _nextIdToTry = id;
88 }
89 }
90 }
91 }
92
93 private sealed class FinalizationHelper
94 {
96
101
103 {
105 int num = ThreadLocal<T>.s_idManager.IdsThatDoNotTrackValuesCount;
106 int i = 0;
107 for (; i < slotArray.Length; i++)
108 {
109 LinkedSlot value = slotArray[i].Value;
110 if (value == null)
111 {
112 continue;
113 }
114 if (num == 0 || ThreadLocal<T>.s_idManager.IdTracksAllValues(i))
115 {
116 value._slotArray = null;
117 continue;
118 }
120 {
121 if (slotArray[i].Value != null)
122 {
123 num--;
124 }
125 if (value._next != null)
126 {
127 value._next._previous = value._previous;
128 }
129 value._previous._next = value._next;
130 }
131 }
132 }
133 }
134
136
139
142
143 private int _idComplement;
144
145 private volatile bool _initialized;
146
147 private static readonly IdManager s_idManager = new IdManager();
148
149 private LinkedSlot _linkedSlot = new LinkedSlot(null);
150
151 private bool _trackAllValues;
152
154 public T Value
155 {
156 [return: MaybeNull]
157 get
158 {
160 int num = ~_idComplement;
162 if (array != null && num >= 0 && num < array.Length && (value = array[num].Value) != null && _initialized)
163 {
164 return value._value;
165 }
166 return GetValueSlow();
167 }
168 set
169 {
171 int num = ~_idComplement;
173 if (array != null && num >= 0 && num < array.Length && (value2 = array[num].Value) != null && _initialized)
174 {
175 value2._value = value;
176 }
177 else
178 {
180 }
181 }
182 }
183
185 {
186 get
187 {
188 if (!_trackAllValues)
189 {
191 }
193 if (valuesAsList == null)
194 {
196 }
197 return valuesAsList;
198 }
199 }
200
202 {
203 get
204 {
205 int num = 0;
207 for (LinkedSlot linkedSlot2 = ((linkedSlot != null) ? linkedSlot._next : null); linkedSlot2 != null; linkedSlot2 = linkedSlot2._next)
208 {
209 num++;
210 }
211 return num;
212 }
213 }
214
215 public bool IsValueCreated
216 {
217 get
218 {
219 int num = ~_idComplement;
220 if (num < 0)
221 {
223 }
225 if (array != null && num < array.Length)
226 {
227 return array[num].Value != null;
228 }
229 return false;
230 }
231 }
232
234 {
235 get
236 {
238 int num = ~_idComplement;
240 if (array == null || num >= array.Length || (value = array[num].Value) == null || !_initialized)
241 {
242 return default(T);
243 }
244 return value._value;
245 }
246 }
247
249
250 public ThreadLocal()
251 {
252 Initialize(null, trackAllValues: false);
253 }
254
256 {
258 }
259
261 {
262 if (valueFactory == null)
263 {
264 throw new ArgumentNullException("valueFactory");
265 }
267 }
268
270 {
271 if (valueFactory == null)
272 {
273 throw new ArgumentNullException("valueFactory");
274 }
276 }
277
279 {
282 _idComplement = ~s_idManager.GetId(trackAllValues);
283 _initialized = true;
284 }
285
287 {
288 Dispose(disposing: false);
289 }
290
291 public void Dispose()
292 {
293 Dispose(disposing: true);
294 GC.SuppressFinalize(this);
295 }
296
297 protected virtual void Dispose(bool disposing)
298 {
299 int num;
301 {
302 num = ~_idComplement;
303 _idComplement = 0;
304 if (num < 0 || !_initialized)
305 {
306 return;
307 }
308 _initialized = false;
309 for (LinkedSlot next = _linkedSlot._next; next != null; next = next._next)
310 {
311 LinkedSlotVolatile[] slotArray = next._slotArray;
312 if (slotArray != null)
313 {
314 next._slotArray = null;
315 slotArray[num].Value._value = default(T);
316 slotArray[num].Value = null;
317 }
318 }
319 }
320 _linkedSlot = null;
321 s_idManager.ReturnId(num, _trackAllValues);
322 }
323
324 public override string? ToString()
325 {
326 return Value.ToString();
327 }
328
329 private T GetValueSlow()
330 {
331 int num = ~_idComplement;
332 if (num < 0)
333 {
335 }
337 T val;
338 if (_valueFactory == null)
339 {
340 val = default(T);
341 }
342 else
343 {
344 val = _valueFactory();
345 if (IsValueCreated)
346 {
348 }
349 }
350 Value = val;
351 return val;
352 }
353
355 {
356 int num = ~_idComplement;
357 if (num < 0)
358 {
360 }
361 if (slotArray == null)
362 {
366 }
367 if (num >= slotArray.Length)
368 {
369 GrowTable(ref slotArray, num + 1);
370 ts_finalizationHelper.SlotArray = slotArray;
372 }
373 if (slotArray[num].Value == null)
374 {
376 return;
377 }
378 LinkedSlot value2 = slotArray[num].Value;
379 if (!_initialized)
380 {
382 }
383 value2._value = value;
384 }
385
387 {
390 {
391 if (!_initialized)
392 {
394 }
395 LinkedSlot linkedSlot2 = (linkedSlot._next = _linkedSlot._next);
396 linkedSlot._previous = _linkedSlot;
397 linkedSlot._value = value;
398 if (linkedSlot2 != null)
399 {
400 linkedSlot2._previous = linkedSlot;
401 }
402 _linkedSlot._next = linkedSlot;
403 slotArray[id].Value = linkedSlot;
404 }
405 }
406
408 {
410 int num = ~_idComplement;
411 if (num == -1 || linkedSlot == null)
412 {
413 return null;
414 }
415 List<T> list = new List<T>();
416 for (linkedSlot = linkedSlot._next; linkedSlot != null; linkedSlot = linkedSlot._next)
417 {
418 list.Add(linkedSlot._value);
419 }
420 return list;
421 }
422
423 private static void GrowTable(ref LinkedSlotVolatile[] table, int minLength)
424 {
425 int newTableSize = GetNewTableSize(minLength);
428 {
429 for (int i = 0; i < table.Length; i++)
430 {
431 LinkedSlot value = table[i].Value;
432 if (value != null && value._slotArray != null)
433 {
434 value._slotArray = array;
435 array[i] = table[i];
436 }
437 }
438 }
439 table = array;
440 }
441
442 private static int GetNewTableSize(int minSize)
443 {
444 if ((uint)minSize > Array.MaxLength)
445 {
446 return int.MaxValue;
447 }
448 int num = minSize;
449 num--;
450 num |= num >> 1;
451 num |= num >> 2;
452 num |= num >> 4;
453 num |= num >> 8;
454 num |= num >> 16;
455 num++;
456 if ((uint)num > Array.MaxLength)
457 {
458 num = Array.MaxLength;
459 }
460 return num;
461 }
462}
static int MaxLength
Definition Array.cs:471
static void NotifyOfCrossThreadDependency()
Definition Debugger.cs:44
static void SuppressFinalize(object obj)
Definition GC.cs:202
Definition GC.cs:8
static string ThreadLocal_ValuesNotAvailable
Definition SR.cs:2006
static string ThreadLocal_Disposed
Definition SR.cs:2002
static string ThreadLocal_Value_RecursiveCallsToValue
Definition SR.cs:2004
Definition SR.cs:7
FinalizationHelper(LinkedSlotVolatile[] slotArray)
int GetId(bool trackAllValues)
void ReturnId(int id, bool idTracksAllValues)
volatile LinkedSlotVolatile[] _slotArray
LinkedSlot(LinkedSlotVolatile[] slotArray)
static readonly IdManager s_idManager
static LinkedSlotVolatile[] ts_slotArray
void SetValueSlow(T value, LinkedSlotVolatile[] slotArray)
static void GrowTable(ref LinkedSlotVolatile[] table, int minLength)
void CreateLinkedSlot(LinkedSlotVolatile[] slotArray, int id, T value)
override? string ToString()
ThreadLocal(bool trackAllValues)
static int GetNewTableSize(int minSize)
ThreadLocal(Func< T > valueFactory, bool trackAllValues)
static FinalizationHelper ts_finalizationHelper
ThreadLocal(Func< T > valueFactory)
virtual void Dispose(bool disposing)
void Initialize(Func< T > valueFactory, bool trackAllValues)