| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399 |
- // Licensed to the .NET Foundation under one or more agreements.
- // The .NET Foundation licenses this file to you under the MIT license.
- // See the LICENSE file in the project root for more information.
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Diagnostics.CodeAnalysis;
- using System.Globalization;
- using System.Runtime.ConstrainedExecution;
- using System.Security.Principal;
- namespace System.Threading
- {
- #if PROJECTN
- [Internal.Runtime.CompilerServices.RelocatedType("System.Threading.Thread")]
- #endif
- public sealed partial class Thread : CriticalFinalizerObject
- {
- private static AsyncLocal<IPrincipal?>? s_asyncLocalPrincipal;
- [ThreadStatic]
- private static Thread? t_currentThread;
- public Thread(ThreadStart start)
- : this()
- {
- if (start == null)
- {
- throw new ArgumentNullException(nameof(start));
- }
- Create(start);
- }
- public Thread(ThreadStart start, int maxStackSize)
- : this()
- {
- if (start == null)
- {
- throw new ArgumentNullException(nameof(start));
- }
- if (maxStackSize < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(maxStackSize), SR.ArgumentOutOfRange_NeedNonNegNum);
- }
- Create(start, maxStackSize);
- }
- public Thread(ParameterizedThreadStart start)
- : this()
- {
- if (start == null)
- {
- throw new ArgumentNullException(nameof(start));
- }
- Create(start);
- }
- public Thread(ParameterizedThreadStart start, int maxStackSize)
- : this()
- {
- if (start == null)
- {
- throw new ArgumentNullException(nameof(start));
- }
- if (maxStackSize < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(maxStackSize), SR.ArgumentOutOfRange_NeedNonNegNum);
- }
- Create(start, maxStackSize);
- }
- private void RequireCurrentThread()
- {
- if (this != CurrentThread)
- {
- throw new InvalidOperationException(SR.Thread_Operation_RequiresCurrentThread);
- }
- }
- private void SetCultureOnUnstartedThread(CultureInfo value, bool uiCulture)
- {
- if (value == null)
- {
- throw new ArgumentNullException(nameof(value));
- }
- if ((ThreadState & ThreadState.Unstarted) == 0)
- {
- throw new InvalidOperationException(SR.Thread_Operation_RequiresCurrentThread);
- }
- SetCultureOnUnstartedThreadNoCheck(value, uiCulture);
- }
- partial void ThreadNameChanged(string? value);
- public CultureInfo CurrentCulture
- {
- get
- {
- RequireCurrentThread();
- return CultureInfo.CurrentCulture;
- }
- set
- {
- if (this != CurrentThread)
- {
- SetCultureOnUnstartedThread(value, uiCulture: false);
- return;
- }
- CultureInfo.CurrentCulture = value;
- }
- }
- public CultureInfo CurrentUICulture
- {
- get
- {
- RequireCurrentThread();
- return CultureInfo.CurrentUICulture;
- }
- set
- {
- if (this != CurrentThread)
- {
- SetCultureOnUnstartedThread(value, uiCulture: true);
- return;
- }
- CultureInfo.CurrentUICulture = value;
- }
- }
- public static IPrincipal? CurrentPrincipal
- {
- get
- {
- if (s_asyncLocalPrincipal is null)
- {
- CurrentPrincipal = AppDomain.CurrentDomain.GetThreadPrincipal();
- }
- return s_asyncLocalPrincipal?.Value;
- }
- set
- {
- if (s_asyncLocalPrincipal is null)
- {
- if (value is null)
- {
- return;
- }
- Interlocked.CompareExchange(ref s_asyncLocalPrincipal, new AsyncLocal<IPrincipal?>(), null);
- }
- s_asyncLocalPrincipal.Value = value;
- }
- }
- public static Thread CurrentThread => t_currentThread ?? InitializeCurrentThread();
- public ExecutionContext? ExecutionContext => ExecutionContext.Capture();
- public string? Name
- {
- get => _name;
- set
- {
- lock (this)
- {
- if (_name != null)
- {
- throw new InvalidOperationException(SR.InvalidOperation_WriteOnce);
- }
- _name = value;
- ThreadNameChanged(value);
- }
- }
- }
- public void Abort()
- {
- throw new PlatformNotSupportedException(SR.PlatformNotSupported_ThreadAbort);
- }
- public void Abort(object? stateInfo)
- {
- throw new PlatformNotSupportedException(SR.PlatformNotSupported_ThreadAbort);
- }
- public static void ResetAbort()
- {
- throw new PlatformNotSupportedException(SR.PlatformNotSupported_ThreadAbort);
- }
- [ObsoleteAttribute("Thread.Suspend has been deprecated. Please use other classes in System.Threading, such as Monitor, Mutex, Event, and Semaphore, to synchronize Threads or protect resources. https://go.microsoft.com/fwlink/?linkid=14202", false)]
- public void Suspend()
- {
- throw new PlatformNotSupportedException(SR.PlatformNotSupported_ThreadSuspend);
- }
- [ObsoleteAttribute("Thread.Resume has been deprecated. Please use other classes in System.Threading, such as Monitor, Mutex, Event, and Semaphore, to synchronize Threads or protect resources. https://go.microsoft.com/fwlink/?linkid=14202", false)]
- public void Resume()
- {
- throw new PlatformNotSupportedException(SR.PlatformNotSupported_ThreadSuspend);
- }
- // Currently, no special handling is done for critical regions, and no special handling is necessary to ensure thread
- // affinity. If that changes, the relevant functions would instead need to delegate to RuntimeThread.
- public static void BeginCriticalRegion() { }
- public static void EndCriticalRegion() { }
- public static void BeginThreadAffinity() { }
- public static void EndThreadAffinity() { }
- public static LocalDataStoreSlot AllocateDataSlot() => LocalDataStore.AllocateSlot();
- public static LocalDataStoreSlot AllocateNamedDataSlot(string name) => LocalDataStore.AllocateNamedSlot(name);
- public static LocalDataStoreSlot GetNamedDataSlot(string name) => LocalDataStore.GetNamedSlot(name);
- public static void FreeNamedDataSlot(string name) => LocalDataStore.FreeNamedSlot(name);
- public static object? GetData(LocalDataStoreSlot slot) => LocalDataStore.GetData(slot);
- public static void SetData(LocalDataStoreSlot slot, object? data) => LocalDataStore.SetData(slot, data);
- [Obsolete("The ApartmentState property has been deprecated. Use GetApartmentState, SetApartmentState or TrySetApartmentState instead.", false)]
- public ApartmentState ApartmentState
- {
- get
- {
- return GetApartmentState();
- }
- set
- {
- TrySetApartmentState(value);
- }
- }
- public void SetApartmentState(ApartmentState state)
- {
- if (!TrySetApartmentState(state))
- {
- throw GetApartmentStateChangeFailedException();
- }
- }
- public bool TrySetApartmentState(ApartmentState state)
- {
- switch (state)
- {
- case ApartmentState.STA:
- case ApartmentState.MTA:
- case ApartmentState.Unknown:
- break;
- default:
- throw new ArgumentOutOfRangeException(SR.ArgumentOutOfRange_Enum, nameof(state));
- }
- return TrySetApartmentStateUnchecked(state);
- }
- [Obsolete("Thread.GetCompressedStack is no longer supported. Please use the System.Threading.CompressedStack class")]
- public CompressedStack GetCompressedStack()
- {
- throw new InvalidOperationException(SR.Thread_GetSetCompressedStack_NotSupported);
- }
- [Obsolete("Thread.SetCompressedStack is no longer supported. Please use the System.Threading.CompressedStack class")]
- public void SetCompressedStack(CompressedStack stack)
- {
- throw new InvalidOperationException(SR.Thread_GetSetCompressedStack_NotSupported);
- }
- public static AppDomain GetDomain() => AppDomain.CurrentDomain;
- public static int GetDomainID() => 1;
- public override int GetHashCode() => ManagedThreadId;
- public void Join() => Join(-1);
- public bool Join(TimeSpan timeout) => Join(WaitHandle.ToTimeoutMilliseconds(timeout));
- public static void MemoryBarrier() => Interlocked.MemoryBarrier();
- public static void Sleep(TimeSpan timeout) => Sleep(WaitHandle.ToTimeoutMilliseconds(timeout));
- public static byte VolatileRead(ref byte address) => Volatile.Read(ref address);
- public static double VolatileRead(ref double address) => Volatile.Read(ref address);
- public static short VolatileRead(ref short address) => Volatile.Read(ref address);
- public static int VolatileRead(ref int address) => Volatile.Read(ref address);
- public static long VolatileRead(ref long address) => Volatile.Read(ref address);
- public static IntPtr VolatileRead(ref IntPtr address) => Volatile.Read(ref address);
- [return: NotNullIfNotNull("address")]
- public static object? VolatileRead(ref object? address) => Volatile.Read(ref address);
- [CLSCompliant(false)]
- public static sbyte VolatileRead(ref sbyte address) => Volatile.Read(ref address);
- public static float VolatileRead(ref float address) => Volatile.Read(ref address);
- [CLSCompliant(false)]
- public static ushort VolatileRead(ref ushort address) => Volatile.Read(ref address);
- [CLSCompliant(false)]
- public static uint VolatileRead(ref uint address) => Volatile.Read(ref address);
- [CLSCompliant(false)]
- public static ulong VolatileRead(ref ulong address) => Volatile.Read(ref address);
- [CLSCompliant(false)]
- public static UIntPtr VolatileRead(ref UIntPtr address) => Volatile.Read(ref address);
- public static void VolatileWrite(ref byte address, byte value) => Volatile.Write(ref address, value);
- public static void VolatileWrite(ref double address, double value) => Volatile.Write(ref address, value);
- public static void VolatileWrite(ref short address, short value) => Volatile.Write(ref address, value);
- public static void VolatileWrite(ref int address, int value) => Volatile.Write(ref address, value);
- public static void VolatileWrite(ref long address, long value) => Volatile.Write(ref address, value);
- public static void VolatileWrite(ref IntPtr address, IntPtr value) => Volatile.Write(ref address, value);
- public static void VolatileWrite([NotNullIfNotNull("value")] ref object? address, object? value) => Volatile.Write(ref address, value);
- [CLSCompliant(false)]
- public static void VolatileWrite(ref sbyte address, sbyte value) => Volatile.Write(ref address, value);
- public static void VolatileWrite(ref float address, float value) => Volatile.Write(ref address, value);
- [CLSCompliant(false)]
- public static void VolatileWrite(ref ushort address, ushort value) => Volatile.Write(ref address, value);
- [CLSCompliant(false)]
- public static void VolatileWrite(ref uint address, uint value) => Volatile.Write(ref address, value);
- [CLSCompliant(false)]
- public static void VolatileWrite(ref ulong address, ulong value) => Volatile.Write(ref address, value);
- [CLSCompliant(false)]
- public static void VolatileWrite(ref UIntPtr address, UIntPtr value) => Volatile.Write(ref address, value);
- /// <summary>
- /// Manages functionality required to support members of <see cref="Thread"/> dealing with thread-local data
- /// </summary>
- private static class LocalDataStore
- {
- private static Dictionary<string, LocalDataStoreSlot>? s_nameToSlotMap;
- public static LocalDataStoreSlot AllocateSlot()
- {
- return new LocalDataStoreSlot(new ThreadLocal<object?>());
- }
- private static Dictionary<string, LocalDataStoreSlot> EnsureNameToSlotMap()
- {
- Dictionary<string, LocalDataStoreSlot>? nameToSlotMap = s_nameToSlotMap;
- if (nameToSlotMap != null)
- {
- return nameToSlotMap;
- }
- nameToSlotMap = new Dictionary<string, LocalDataStoreSlot>();
- return Interlocked.CompareExchange(ref s_nameToSlotMap, nameToSlotMap, null) ?? nameToSlotMap;
- }
- public static LocalDataStoreSlot AllocateNamedSlot(string name)
- {
- LocalDataStoreSlot slot = AllocateSlot();
- Dictionary<string, LocalDataStoreSlot> nameToSlotMap = EnsureNameToSlotMap();
- lock (nameToSlotMap)
- {
- nameToSlotMap.Add(name, slot);
- }
- return slot;
- }
- public static LocalDataStoreSlot GetNamedSlot(string name)
- {
- Dictionary<string, LocalDataStoreSlot> nameToSlotMap = EnsureNameToSlotMap();
- lock (nameToSlotMap)
- {
- LocalDataStoreSlot? slot;
- if (!nameToSlotMap.TryGetValue(name, out slot))
- {
- slot = AllocateSlot();
- nameToSlotMap[name] = slot;
- }
- return slot;
- }
- }
- public static void FreeNamedSlot(string name)
- {
- Dictionary<string, LocalDataStoreSlot> nameToSlotMap = EnsureNameToSlotMap();
- lock (nameToSlotMap)
- {
- nameToSlotMap.Remove(name);
- }
- }
- private static ThreadLocal<object?> GetThreadLocal(LocalDataStoreSlot slot)
- {
- if (slot == null)
- {
- throw new ArgumentNullException(nameof(slot));
- }
- Debug.Assert(slot.Data != null);
- return slot.Data;
- }
- public static object? GetData(LocalDataStoreSlot slot)
- {
- return GetThreadLocal(slot).Value;
- }
- public static void SetData(LocalDataStoreSlot slot, object? value)
- {
- GetThreadLocal(slot).Value = value;
- }
- }
- }
- }
|