Delete PROJECTN ifdefs from Corelib (dotnet/coreclr#26058)
[mono-project.git] / netcore / System.Private.CoreLib / shared / System / Threading / Thread.cs
blob9b7abbf9fbb03260e6a3f30041c8127905bbccd0
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 using System.Collections.Generic;
6 using System.Diagnostics;
7 using System.Diagnostics.CodeAnalysis;
8 using System.Globalization;
9 using System.Runtime.ConstrainedExecution;
10 using System.Security.Principal;
12 namespace System.Threading
14 public sealed partial class Thread : CriticalFinalizerObject
16 private static AsyncLocal<IPrincipal?>? s_asyncLocalPrincipal;
18 [ThreadStatic]
19 private static Thread? t_currentThread;
21 public Thread(ThreadStart start)
22 : this()
24 if (start == null)
26 throw new ArgumentNullException(nameof(start));
29 Create(start);
32 public Thread(ThreadStart start, int maxStackSize)
33 : this()
35 if (start == null)
37 throw new ArgumentNullException(nameof(start));
39 if (maxStackSize < 0)
41 throw new ArgumentOutOfRangeException(nameof(maxStackSize), SR.ArgumentOutOfRange_NeedNonNegNum);
44 Create(start, maxStackSize);
47 public Thread(ParameterizedThreadStart start)
48 : this()
50 if (start == null)
52 throw new ArgumentNullException(nameof(start));
55 Create(start);
58 public Thread(ParameterizedThreadStart start, int maxStackSize)
59 : this()
61 if (start == null)
63 throw new ArgumentNullException(nameof(start));
65 if (maxStackSize < 0)
67 throw new ArgumentOutOfRangeException(nameof(maxStackSize), SR.ArgumentOutOfRange_NeedNonNegNum);
70 Create(start, maxStackSize);
73 private void RequireCurrentThread()
75 if (this != CurrentThread)
77 throw new InvalidOperationException(SR.Thread_Operation_RequiresCurrentThread);
81 private void SetCultureOnUnstartedThread(CultureInfo value, bool uiCulture)
83 if (value == null)
85 throw new ArgumentNullException(nameof(value));
87 if ((ThreadState & ThreadState.Unstarted) == 0)
89 throw new InvalidOperationException(SR.Thread_Operation_RequiresCurrentThread);
91 SetCultureOnUnstartedThreadNoCheck(value, uiCulture);
94 partial void ThreadNameChanged(string? value);
96 public CultureInfo CurrentCulture
98 get
100 RequireCurrentThread();
101 return CultureInfo.CurrentCulture;
105 if (this != CurrentThread)
107 SetCultureOnUnstartedThread(value, uiCulture: false);
108 return;
110 CultureInfo.CurrentCulture = value;
114 public CultureInfo CurrentUICulture
118 RequireCurrentThread();
119 return CultureInfo.CurrentUICulture;
123 if (this != CurrentThread)
125 SetCultureOnUnstartedThread(value, uiCulture: true);
126 return;
128 CultureInfo.CurrentUICulture = value;
132 public static IPrincipal? CurrentPrincipal
136 if (s_asyncLocalPrincipal is null)
138 CurrentPrincipal = AppDomain.CurrentDomain.GetThreadPrincipal();
140 return s_asyncLocalPrincipal?.Value;
144 if (s_asyncLocalPrincipal is null)
146 if (value is null)
148 return;
150 Interlocked.CompareExchange(ref s_asyncLocalPrincipal, new AsyncLocal<IPrincipal?>(), null);
152 s_asyncLocalPrincipal.Value = value;
156 public static Thread CurrentThread => t_currentThread ?? InitializeCurrentThread();
158 public ExecutionContext? ExecutionContext => ExecutionContext.Capture();
160 public string? Name
162 get => _name;
165 lock (this)
167 if (_name != null)
169 throw new InvalidOperationException(SR.InvalidOperation_WriteOnce);
172 _name = value;
174 ThreadNameChanged(value);
179 public void Abort()
181 throw new PlatformNotSupportedException(SR.PlatformNotSupported_ThreadAbort);
184 public void Abort(object? stateInfo)
186 throw new PlatformNotSupportedException(SR.PlatformNotSupported_ThreadAbort);
189 public static void ResetAbort()
191 throw new PlatformNotSupportedException(SR.PlatformNotSupported_ThreadAbort);
194 [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)]
195 public void Suspend()
197 throw new PlatformNotSupportedException(SR.PlatformNotSupported_ThreadSuspend);
200 [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)]
201 public void Resume()
203 throw new PlatformNotSupportedException(SR.PlatformNotSupported_ThreadSuspend);
206 // Currently, no special handling is done for critical regions, and no special handling is necessary to ensure thread
207 // affinity. If that changes, the relevant functions would instead need to delegate to RuntimeThread.
208 public static void BeginCriticalRegion() { }
209 public static void EndCriticalRegion() { }
210 public static void BeginThreadAffinity() { }
211 public static void EndThreadAffinity() { }
213 public static LocalDataStoreSlot AllocateDataSlot() => LocalDataStore.AllocateSlot();
214 public static LocalDataStoreSlot AllocateNamedDataSlot(string name) => LocalDataStore.AllocateNamedSlot(name);
215 public static LocalDataStoreSlot GetNamedDataSlot(string name) => LocalDataStore.GetNamedSlot(name);
216 public static void FreeNamedDataSlot(string name) => LocalDataStore.FreeNamedSlot(name);
217 public static object? GetData(LocalDataStoreSlot slot) => LocalDataStore.GetData(slot);
218 public static void SetData(LocalDataStoreSlot slot, object? data) => LocalDataStore.SetData(slot, data);
220 [Obsolete("The ApartmentState property has been deprecated. Use GetApartmentState, SetApartmentState or TrySetApartmentState instead.", false)]
221 public ApartmentState ApartmentState
225 return GetApartmentState();
229 TrySetApartmentState(value);
233 public void SetApartmentState(ApartmentState state)
235 if (!TrySetApartmentState(state))
237 throw GetApartmentStateChangeFailedException();
241 public bool TrySetApartmentState(ApartmentState state)
243 switch (state)
245 case ApartmentState.STA:
246 case ApartmentState.MTA:
247 case ApartmentState.Unknown:
248 break;
250 default:
251 throw new ArgumentOutOfRangeException(SR.ArgumentOutOfRange_Enum, nameof(state));
254 return TrySetApartmentStateUnchecked(state);
257 [Obsolete("Thread.GetCompressedStack is no longer supported. Please use the System.Threading.CompressedStack class")]
258 public CompressedStack GetCompressedStack()
260 throw new InvalidOperationException(SR.Thread_GetSetCompressedStack_NotSupported);
263 [Obsolete("Thread.SetCompressedStack is no longer supported. Please use the System.Threading.CompressedStack class")]
264 public void SetCompressedStack(CompressedStack stack)
266 throw new InvalidOperationException(SR.Thread_GetSetCompressedStack_NotSupported);
269 public static AppDomain GetDomain() => AppDomain.CurrentDomain;
270 public static int GetDomainID() => 1;
271 public override int GetHashCode() => ManagedThreadId;
272 public void Join() => Join(-1);
273 public bool Join(TimeSpan timeout) => Join(WaitHandle.ToTimeoutMilliseconds(timeout));
274 public static void MemoryBarrier() => Interlocked.MemoryBarrier();
275 public static void Sleep(TimeSpan timeout) => Sleep(WaitHandle.ToTimeoutMilliseconds(timeout));
277 public static byte VolatileRead(ref byte address) => Volatile.Read(ref address);
278 public static double VolatileRead(ref double address) => Volatile.Read(ref address);
279 public static short VolatileRead(ref short address) => Volatile.Read(ref address);
280 public static int VolatileRead(ref int address) => Volatile.Read(ref address);
281 public static long VolatileRead(ref long address) => Volatile.Read(ref address);
282 public static IntPtr VolatileRead(ref IntPtr address) => Volatile.Read(ref address);
283 [return: NotNullIfNotNull("address")]
284 public static object? VolatileRead(ref object? address) => Volatile.Read(ref address);
285 [CLSCompliant(false)]
286 public static sbyte VolatileRead(ref sbyte address) => Volatile.Read(ref address);
287 public static float VolatileRead(ref float address) => Volatile.Read(ref address);
288 [CLSCompliant(false)]
289 public static ushort VolatileRead(ref ushort address) => Volatile.Read(ref address);
290 [CLSCompliant(false)]
291 public static uint VolatileRead(ref uint address) => Volatile.Read(ref address);
292 [CLSCompliant(false)]
293 public static ulong VolatileRead(ref ulong address) => Volatile.Read(ref address);
294 [CLSCompliant(false)]
295 public static UIntPtr VolatileRead(ref UIntPtr address) => Volatile.Read(ref address);
296 public static void VolatileWrite(ref byte address, byte value) => Volatile.Write(ref address, value);
297 public static void VolatileWrite(ref double address, double value) => Volatile.Write(ref address, value);
298 public static void VolatileWrite(ref short address, short value) => Volatile.Write(ref address, value);
299 public static void VolatileWrite(ref int address, int value) => Volatile.Write(ref address, value);
300 public static void VolatileWrite(ref long address, long value) => Volatile.Write(ref address, value);
301 public static void VolatileWrite(ref IntPtr address, IntPtr value) => Volatile.Write(ref address, value);
302 public static void VolatileWrite([NotNullIfNotNull("value")] ref object? address, object? value) => Volatile.Write(ref address, value);
303 [CLSCompliant(false)]
304 public static void VolatileWrite(ref sbyte address, sbyte value) => Volatile.Write(ref address, value);
305 public static void VolatileWrite(ref float address, float value) => Volatile.Write(ref address, value);
306 [CLSCompliant(false)]
307 public static void VolatileWrite(ref ushort address, ushort value) => Volatile.Write(ref address, value);
308 [CLSCompliant(false)]
309 public static void VolatileWrite(ref uint address, uint value) => Volatile.Write(ref address, value);
310 [CLSCompliant(false)]
311 public static void VolatileWrite(ref ulong address, ulong value) => Volatile.Write(ref address, value);
312 [CLSCompliant(false)]
313 public static void VolatileWrite(ref UIntPtr address, UIntPtr value) => Volatile.Write(ref address, value);
315 /// <summary>
316 /// Manages functionality required to support members of <see cref="Thread"/> dealing with thread-local data
317 /// </summary>
318 private static class LocalDataStore
320 private static Dictionary<string, LocalDataStoreSlot>? s_nameToSlotMap;
322 public static LocalDataStoreSlot AllocateSlot()
324 return new LocalDataStoreSlot(new ThreadLocal<object?>());
327 private static Dictionary<string, LocalDataStoreSlot> EnsureNameToSlotMap()
329 Dictionary<string, LocalDataStoreSlot>? nameToSlotMap = s_nameToSlotMap;
330 if (nameToSlotMap != null)
332 return nameToSlotMap;
335 nameToSlotMap = new Dictionary<string, LocalDataStoreSlot>();
336 return Interlocked.CompareExchange(ref s_nameToSlotMap, nameToSlotMap, null) ?? nameToSlotMap;
339 public static LocalDataStoreSlot AllocateNamedSlot(string name)
341 LocalDataStoreSlot slot = AllocateSlot();
342 Dictionary<string, LocalDataStoreSlot> nameToSlotMap = EnsureNameToSlotMap();
343 lock (nameToSlotMap)
345 nameToSlotMap.Add(name, slot);
347 return slot;
350 public static LocalDataStoreSlot GetNamedSlot(string name)
352 Dictionary<string, LocalDataStoreSlot> nameToSlotMap = EnsureNameToSlotMap();
353 lock (nameToSlotMap)
355 LocalDataStoreSlot? slot;
356 if (!nameToSlotMap.TryGetValue(name, out slot))
358 slot = AllocateSlot();
359 nameToSlotMap[name] = slot;
361 return slot;
365 public static void FreeNamedSlot(string name)
367 Dictionary<string, LocalDataStoreSlot> nameToSlotMap = EnsureNameToSlotMap();
368 lock (nameToSlotMap)
370 nameToSlotMap.Remove(name);
374 private static ThreadLocal<object?> GetThreadLocal(LocalDataStoreSlot slot)
376 if (slot == null)
378 throw new ArgumentNullException(nameof(slot));
381 Debug.Assert(slot.Data != null);
382 return slot.Data;
385 public static object? GetData(LocalDataStoreSlot slot)
387 return GetThreadLocal(slot).Value;
390 public static void SetData(LocalDataStoreSlot slot, object? value)
392 GetThreadLocal(slot).Value = value;