9 [DebuggerTypeProxy(typeof(SystemThreading_ThreadLocalDebugView<>))]
10 [DebuggerDisplay(
"IsValueCreated={IsValueCreated}, Value={ValueForDebugDisplay}, Count={ValuesCountForDebugDisplay}")]
11 [__DynamicallyInvokable]
12 [HostProtection(
SecurityAction.LinkDemand, Synchronization =
true, ExternalThreading =
true)]
15 private struct LinkedSlotVolatile
17 internal volatile LinkedSlot
Value;
20 private sealed
class LinkedSlot
22 internal volatile LinkedSlot Next;
24 internal volatile LinkedSlot Previous;
26 internal volatile LinkedSlotVolatile[] SlotArray;
30 internal LinkedSlot(LinkedSlotVolatile[] slotArray)
32 SlotArray = slotArray;
36 private class IdManager
38 private int m_nextIdToTry;
47 for (i = m_nextIdToTry; i < m_freeIds.
Count && !m_freeIds[i]; i++)
50 if (i == m_freeIds.
Count)
52 m_freeIds.
Add(item:
false);
58 m_nextIdToTry = i + 1;
63 internal void ReturnId(
int id)
68 if (
id < m_nextIdToTry)
76 private class FinalizationHelper
78 internal LinkedSlotVolatile[] SlotArray;
80 private bool m_trackAllValues;
82 internal FinalizationHelper(LinkedSlotVolatile[] slotArray,
bool trackAllValues)
84 SlotArray = slotArray;
85 m_trackAllValues = trackAllValues;
90 LinkedSlotVolatile[] slotArray = SlotArray;
92 for (; i < slotArray.Length; i++)
94 LinkedSlot value = slotArray[i].Value;
99 value.SlotArray =
null;
105 if (value.Next !=
null)
107 value.Next.Previous = value.Previous;
109 value.Previous.Next = value.Next;
117 private Func<T> m_valueFactory;
120 private static LinkedSlotVolatile[] ts_slotArray;
123 private static FinalizationHelper ts_finalizationHelper;
125 private int m_idComplement;
127 private volatile bool m_initialized;
129 private static IdManager s_idManager =
new IdManager();
131 private LinkedSlot m_linkedSlot =
new LinkedSlot(
null);
133 private bool m_trackAllValues;
141 [__DynamicallyInvokable]
144 [__DynamicallyInvokable]
147 LinkedSlotVolatile[] array = ts_slotArray;
148 int num = ~m_idComplement;
150 if (array !=
null && num >= 0 && num < array.Length && (value = array[num].Value) !=
null && m_initialized)
154 return GetValueSlow();
156 [__DynamicallyInvokable]
159 LinkedSlotVolatile[] array = ts_slotArray;
160 int num = ~m_idComplement;
162 if (array !=
null && num >= 0 && num < array.Length && (value2 = array[num].Value) !=
null && m_initialized)
164 value2.Value = value;
168 SetValueSlow(value, array);
177 [__DynamicallyInvokable]
180 [__DynamicallyInvokable]
183 if (!m_trackAllValues)
187 List<T> valuesAsList = GetValuesAsList();
188 if (valuesAsList ==
null)
196 private int ValuesCountForDebugDisplay
201 for (LinkedSlot next = m_linkedSlot.Next; next !=
null; next = next.Next)
212 [__DynamicallyInvokable]
215 [__DynamicallyInvokable]
218 int num = ~m_idComplement;
223 LinkedSlotVolatile[] array = ts_slotArray;
224 if (array !=
null && num < array.Length)
226 return array[num].Value !=
null;
232 internal T ValueForDebugDisplay
236 LinkedSlotVolatile[] array = ts_slotArray;
237 int num = ~m_idComplement;
239 if (array ==
null || num >= array.Length || (value = array[num].Value) ==
null || !m_initialized)
247 internal List<T> ValuesForDebugDisplay => GetValuesAsList();
250 [__DynamicallyInvokable]
253 Initialize(
null, trackAllValues:
false);
259 [__DynamicallyInvokable]
262 Initialize(
null, trackAllValues);
269 [__DynamicallyInvokable]
272 if (valueFactory ==
null)
276 Initialize(valueFactory, trackAllValues:
false);
285 [__DynamicallyInvokable]
288 if (valueFactory ==
null)
292 Initialize(valueFactory, trackAllValues);
295 private void Initialize(Func<T> valueFactory,
bool trackAllValues)
297 m_valueFactory = valueFactory;
298 m_trackAllValues = trackAllValues;
304 m_idComplement = ~s_idManager.GetId();
305 m_initialized =
true;
310 [__DynamicallyInvokable]
317 [__DynamicallyInvokable]
326 [__DynamicallyInvokable]
327 protected virtual void Dispose(
bool disposing)
332 num = ~m_idComplement;
334 if (num < 0 || !m_initialized)
338 m_initialized =
false;
339 for (LinkedSlot next = m_linkedSlot.Next; next !=
null; next = next.Next)
341 LinkedSlotVolatile[] slotArray = next.SlotArray;
342 if (slotArray !=
null)
344 next.SlotArray =
null;
345 slotArray[num].Value.Value =
default(
T);
346 slotArray[num].Value =
null;
351 s_idManager.ReturnId(num);
360 [__DynamicallyInvokable]
363 return Value.ToString();
366 private T GetValueSlow()
368 int num = ~m_idComplement;
375 if (m_valueFactory ==
null)
381 val = m_valueFactory();
384 throw new InvalidOperationException(Environment.GetResourceString(
"ThreadLocal_Value_RecursiveCallsToValue"));
391 private void SetValueSlow(T value, LinkedSlotVolatile[] slotArray)
393 int num = ~m_idComplement;
396 throw new ObjectDisposedException(Environment.GetResourceString(
"ThreadLocal_Disposed"));
398 if (slotArray ==
null)
400 slotArray =
new LinkedSlotVolatile[GetNewTableSize(num + 1)];
401 ts_finalizationHelper =
new FinalizationHelper(slotArray, m_trackAllValues);
402 ts_slotArray = slotArray;
404 if (num >= slotArray.Length)
406 GrowTable(ref slotArray, num + 1);
407 ts_finalizationHelper.SlotArray = slotArray;
408 ts_slotArray = slotArray;
410 if (slotArray[num].
Value ==
null)
412 CreateLinkedSlot(slotArray, num, value);
415 LinkedSlot value2 = slotArray[num].Value;
418 throw new ObjectDisposedException(Environment.GetResourceString(
"ThreadLocal_Disposed"));
420 value2.Value = value;
423 private void CreateLinkedSlot(LinkedSlotVolatile[] slotArray,
int id, T value)
425 LinkedSlot linkedSlot =
new LinkedSlot(slotArray);
430 throw new ObjectDisposedException(Environment.GetResourceString(
"ThreadLocal_Disposed"));
432 LinkedSlot linkedSlot2 = linkedSlot.Next = m_linkedSlot.Next;
433 linkedSlot.Previous = m_linkedSlot;
434 linkedSlot.Value = value;
435 if (linkedSlot2 !=
null)
437 linkedSlot2.Previous = linkedSlot;
439 m_linkedSlot.Next = linkedSlot;
440 slotArray[id].Value = linkedSlot;
444 private List<T> GetValuesAsList()
447 int num = ~m_idComplement;
452 for (LinkedSlot next = m_linkedSlot.Next; next !=
null; next = next.Next)
454 list.Add(next.Value);
459 private void GrowTable(ref LinkedSlotVolatile[] table,
int minLength)
461 int newTableSize = GetNewTableSize(minLength);
462 LinkedSlotVolatile[] array =
new LinkedSlotVolatile[newTableSize];
465 for (
int i = 0; i < table.Length; i++)
467 LinkedSlot value = table[i].Value;
468 if (value !=
null && value.SlotArray !=
null)
470 value.SlotArray = array;
478 private static int GetNewTableSize(
int minSize)
480 if ((uint)minSize > 2146435071u)
484 int num = minSize - 1;
491 if ((uint)num > 2146435071u)
The exception that is thrown when a null reference (Nothing in Visual Basic) is passed to a method th...
override string ToString()
Creates and returns a string representation of this instance for the current thread.
T Value
Gets or sets the value of this instance for the current thread.
int Count
Gets the number of elements contained in the T:System.Collections.Generic.List`1.
static void SuppressFinalize(object obj)
Requests that the common language runtime not call the finalizer for the specified object.
ThreadLocal(Func< T > valueFactory)
Initializes the T:System.Threading.ThreadLocal`1 instance with the specified valueFactory function.
ThreadLocal()
Initializes the T:System.Threading.ThreadLocal`1 instance.
Provides a mechanism for releasing unmanaged resources.To browse the .NET Framework source code for t...
The exception that is thrown when an operation is performed on a disposed object.
void Add(T item)
Adds an object to the end of the T:System.Collections.Generic.List`1.
SecurityAction
Specifies the security actions that can be performed using declarative security.
Provides information about, and means to manipulate, the current environment and platform....
Enables communication with a debugger. This class cannot be inherited.
Controls the system garbage collector, a service that automatically reclaims unused memory.
ThreadLocal(bool trackAllValues)
Initializes the T:System.Threading.ThreadLocal`1 instance and specifies whether all values are access...
Provides thread-local storage of data.
void Dispose()
Releases all resources used by the current instance of the T:System.Threading.ThreadLocal`1 class.
Represents a collection of objects that can be individually accessed by index.
ThreadLocal(Func< T > valueFactory, bool trackAllValues)
Initializes the T:System.Threading.ThreadLocal`1 instance with the specified valueFactory function a...
virtual void Dispose(bool disposing)
Releases the resources used by this T:System.Threading.ThreadLocal`1 instance.
The exception that is thrown when a method call is invalid for the object's current state.
bool IsValueCreated
Gets whether P:System.Threading.ThreadLocal`1.Value is initialized on the current thread.
static void NotifyOfCrossThreadDependency()
Notifies a debugger that execution is about to enter a path that involves a cross-thread dependency.
IList< T > Values
Gets a list for all of the values currently stored by all of the threads that have accessed this inst...
DebuggerBrowsableState
Provides display instructions for the debugger.