2 // System.Threading.Thread.cs
5 // Dick Porter (dick@ximian.com)
7 // (C) Ximian, Inc. http://www.ximian.com
10 using System.Runtime.Remoting.Contexts;
11 using System.Security.Principal;
12 using System.Globalization;
13 using System.Runtime.CompilerServices;
14 using System.Collections;
16 namespace System.Threading
18 public sealed class Thread
20 // stores a thread handle
21 private IntPtr system_thread_handle;
23 private CultureInfo current_culture;
24 private bool threadpool_thread;
25 private ThreadState state = ThreadState.Unstarted;
26 private object abort_exc;
27 internal object abort_state;
28 /* thread_id is only accessed from unmanaged code */
29 private int thread_id;
31 /* start_notify is used by the runtime to signal that Start()
34 private IntPtr start_notify;
35 private IntPtr stack_ptr;
36 private IntPtr static_data;
37 private IntPtr jit_data;
38 private IntPtr lock_data;
40 private ThreadStart threadstart;
41 private string thread_name=null;
44 public static Context CurrentContext {
46 return(AppDomain.InternalGetContext ());
51 public static IPrincipal CurrentPrincipal {
54 // System.Security.Principal.IPrincipal
55 // not yet implemented
63 // Looks up the object associated with the current thread
64 [MethodImplAttribute(MethodImplOptions.InternalCall)]
65 private extern static Thread CurrentThread_internal();
67 public static Thread CurrentThread {
69 return(CurrentThread_internal());
73 internal static int CurrentThreadId {
75 return CurrentThread.thread_id;
79 // Looks up the slot hash for the current thread
80 [MethodImplAttribute(MethodImplOptions.InternalCall)]
81 private extern static Hashtable SlotHash_lookup();
83 // Stores the slot hash for the current thread
84 [MethodImplAttribute(MethodImplOptions.InternalCall)]
85 private extern static void SlotHash_store(Hashtable slothash);
87 private static Hashtable GetTLSSlotHash() {
88 Hashtable slothash=SlotHash_lookup();
90 // Not synchronised, because this is
91 // thread specific anyway.
92 slothash=new Hashtable();
93 SlotHash_store(slothash);
99 internal static object ResetDataStoreStatus () {
100 Hashtable slothash=SlotHash_lookup();
101 SlotHash_store(null);
105 internal static void RestoreDataStoreStatus (object data) {
106 SlotHash_store((Hashtable)data);
109 public static LocalDataStoreSlot AllocateDataSlot() {
110 LocalDataStoreSlot slot = new LocalDataStoreSlot();
115 // Stores a hash keyed by strings of LocalDataStoreSlot objects
116 static Hashtable datastorehash;
118 private static void InitDataStoreHash () {
119 lock (typeof (Thread)) {
120 if (datastorehash == null) {
121 datastorehash = Hashtable.Synchronized(new Hashtable());
126 public static LocalDataStoreSlot AllocateNamedDataSlot(string name) {
127 lock (typeof (Thread)) {
128 if (datastorehash == null)
129 InitDataStoreHash ();
130 LocalDataStoreSlot slot = (LocalDataStoreSlot)datastorehash[name];
132 // This exception isnt documented (of
133 // course) but .net throws it
134 throw new ArgumentException("Named data slot already added");
137 slot = new LocalDataStoreSlot();
139 datastorehash.Add(name, slot);
145 public static void FreeNamedDataSlot(string name) {
146 lock (typeof (Thread)) {
147 if (datastorehash == null)
148 InitDataStoreHash ();
149 LocalDataStoreSlot slot=(LocalDataStoreSlot)datastorehash[name];
152 datastorehash.Remove(slot);
157 public static object GetData(LocalDataStoreSlot slot) {
158 Hashtable slothash=GetTLSSlotHash();
159 return(slothash[slot]);
162 public static AppDomain GetDomain() {
163 return AppDomain.CurrentDomain;
166 [MethodImplAttribute(MethodImplOptions.InternalCall)]
167 public extern static int GetDomainID();
169 public static LocalDataStoreSlot GetNamedDataSlot(string name) {
170 if (datastorehash == null)
171 InitDataStoreHash ();
172 LocalDataStoreSlot slot=(LocalDataStoreSlot)datastorehash[name];
175 slot=AllocateNamedDataSlot(name);
181 [MethodImplAttribute(MethodImplOptions.InternalCall)]
182 private extern static void ResetAbort_internal();
184 public static void ResetAbort()
186 Thread thread=CurrentThread;
188 thread.clr_state(ThreadState.AbortRequested);
189 ResetAbort_internal();
193 public static void SetData(LocalDataStoreSlot slot,
195 Hashtable slothash=GetTLSSlotHash();
197 if(slothash.Contains(slot)) {
198 slothash.Remove(slot);
201 slothash.Add(slot, data);
204 [MethodImplAttribute(MethodImplOptions.InternalCall)]
205 private extern static void Sleep_internal(int ms);
207 public static void Sleep(int millisecondsTimeout) {
208 if((millisecondsTimeout<0) && (millisecondsTimeout != Timeout.Infinite)) {
209 throw new ArgumentException("Negative timeout");
211 Thread thread=CurrentThread;
213 thread.set_state(ThreadState.WaitSleepJoin);
215 Sleep_internal(millisecondsTimeout);
216 thread.clr_state(ThreadState.WaitSleepJoin);
219 public static void Sleep(TimeSpan timeout) {
220 // LAMESPEC: says to throw ArgumentException too
221 int ms=Convert.ToInt32(timeout.TotalMilliseconds);
223 if(ms < 0 || ms > Int32.MaxValue) {
224 throw new ArgumentOutOfRangeException("Timeout out of range");
227 Thread thread=CurrentThread;
229 thread.set_state(ThreadState.WaitSleepJoin);
231 thread.clr_state(ThreadState.WaitSleepJoin);
234 // Returns the system thread handle
235 [MethodImplAttribute(MethodImplOptions.InternalCall)]
236 private extern IntPtr Thread_internal(ThreadStart start);
238 public Thread(ThreadStart start) {
240 throw new ArgumentNullException("Null ThreadStart");
244 // This is a two-stage thread launch. Thread_internal
245 // creates the new thread, but blocks it until
246 // Start() is called later.
247 system_thread_handle=Thread_internal(start);
249 // Should throw an exception here if
250 // Thread_internal returns NULL
251 if(system_thread_handle==(IntPtr)0) {
252 throw new SystemException("Thread creation failed");
257 public ApartmentState ApartmentState {
260 return(ApartmentState.Unknown);
268 public CultureInfo CurrentCulture {
270 if (current_culture == null)
271 current_culture = CultureInfo.InvariantCulture;
272 return current_culture;
276 current_culture = value;
281 public CultureInfo CurrentUICulture {
284 return(CurrentCulture);
289 CurrentCulture=value;
293 public bool IsThreadPoolThread {
295 return IsThreadPoolThreadInternal;
299 internal bool IsThreadPoolThreadInternal {
301 return threadpool_thread;
304 threadpool_thread = value;
308 public bool IsAlive {
310 ThreadState curstate=state;
312 if((curstate & ThreadState.Aborted) != 0 ||
313 (curstate & ThreadState.Stopped) != 0 ||
314 (curstate & ThreadState.Unstarted) != 0) {
322 public bool IsBackground {
324 if((state & ThreadState.Background) != 0) {
333 set_state(ThreadState.Background);
335 clr_state(ThreadState.Background);
351 public ThreadPriority Priority {
354 return(ThreadPriority.Lowest);
361 public ThreadState ThreadState {
367 [MethodImplAttribute(MethodImplOptions.InternalCall)]
368 private extern void Abort_internal (object stateInfo);
370 public void Abort() {
371 set_state(ThreadState.AbortRequested);
372 Abort_internal (null);
375 public void Abort(object stateInfo) {
376 set_state(ThreadState.AbortRequested);
377 Abort_internal(stateInfo);
382 public void Interrupt() {
386 // The current thread joins with 'this'. Set ms to 0 to block
387 // until this actually exits.
388 [MethodImplAttribute(MethodImplOptions.InternalCall)]
389 private extern bool Join_internal(int ms, IntPtr handle);
392 if((state & ThreadState.Unstarted) != 0) {
393 throw new ThreadStateException("Thread has not been started");
396 Thread thread=CurrentThread;
398 thread.set_state(ThreadState.WaitSleepJoin);
399 Join_internal(Timeout.Infinite, system_thread_handle);
400 thread.clr_state(ThreadState.WaitSleepJoin);
403 public bool Join(int millisecondsTimeout) {
404 if (millisecondsTimeout != Timeout.Infinite && millisecondsTimeout < 0)
405 throw new ArgumentException ("Timeout less than zero", "millisecondsTimeout");
407 if((state & ThreadState.Unstarted) != 0) {
408 throw new ThreadStateException("Thread has not been started");
411 Thread thread=CurrentThread;
413 thread.set_state(ThreadState.WaitSleepJoin);
414 bool ret=Join_internal(millisecondsTimeout,
415 system_thread_handle);
416 thread.clr_state(ThreadState.WaitSleepJoin);
421 public bool Join(TimeSpan timeout) {
422 // LAMESPEC: says to throw ArgumentException too
423 int ms=Convert.ToInt32(timeout.TotalMilliseconds);
425 if(ms < 0 || ms > Int32.MaxValue) {
426 throw new ArgumentOutOfRangeException("timeout out of range");
428 if((state & ThreadState.Unstarted) != 0) {
429 throw new ThreadStateException("Thread has not been started");
432 Thread thread=CurrentThread;
434 thread.set_state(ThreadState.WaitSleepJoin);
435 bool ret=Join_internal(ms, system_thread_handle);
436 thread.clr_state(ThreadState.WaitSleepJoin);
442 public void Resume() {
443 throw new NotImplementedException ();
446 // Launches the thread
447 [MethodImplAttribute(MethodImplOptions.InternalCall)]
448 private extern void Start_internal(IntPtr handle);
450 public void Start() {
452 if((state & ThreadState.Unstarted) == 0) {
453 throw new ThreadStateException("Thread has already been started");
456 // Launch this thread
457 Start_internal(system_thread_handle);
459 // Mark the thread state as Running
460 // (which is all bits
461 // cleared). Therefore just remove the
463 clr_state(ThreadState.Unstarted);
468 public void Suspend() {
469 if((state & ThreadState.Unstarted) != 0 || !IsAlive) {
470 throw new ThreadStateException("Thread has not been started, or is dead");
473 set_state(ThreadState.SuspendRequested);
474 // FIXME - somehow let the interpreter know that
475 // this thread should now suspend
476 Console.WriteLine ("WARNING: Thread.Suspend () partially implemented");
479 // Closes the system thread handle
480 [MethodImplAttribute(MethodImplOptions.InternalCall)]
481 private extern void Thread_free_internal(IntPtr handle);
484 // Free up the handle
485 Thread_free_internal(system_thread_handle);
488 private void set_state(ThreadState set) {
493 private void clr_state(ThreadState clr) {
500 [MethodImplAttribute (MethodImplOptions.InternalCall)]
501 extern public static byte VolatileRead (ref byte address);
503 [MethodImplAttribute (MethodImplOptions.InternalCall)]
504 extern public static double VolatileRead (ref double address);
506 [MethodImplAttribute (MethodImplOptions.InternalCall)]
507 extern public static short VolatileRead (ref short address);
509 [MethodImplAttribute (MethodImplOptions.InternalCall)]
510 extern public static int VolatileRead (ref int address);
512 [MethodImplAttribute (MethodImplOptions.InternalCall)]
513 extern public static long VolatileRead (ref long address);
515 [MethodImplAttribute (MethodImplOptions.InternalCall)]
516 extern public static IntPtr VolatileRead (ref IntPtr address);
518 [MethodImplAttribute (MethodImplOptions.InternalCall)]
519 extern public static object VolatileRead (ref object address);
521 [CLSCompliant(false)]
522 [MethodImplAttribute (MethodImplOptions.InternalCall)]
523 extern public static sbyte VolatileRead (ref sbyte address);
525 [MethodImplAttribute (MethodImplOptions.InternalCall)]
526 extern public static float VolatileRead (ref float address);
528 [CLSCompliant (false)]
529 [MethodImplAttribute (MethodImplOptions.InternalCall)]
530 extern public static ushort VolatileRead (ref ushort address);
532 [CLSCompliant (false)]
533 [MethodImplAttribute (MethodImplOptions.InternalCall)]
534 extern public static uint VolatileRead (ref uint address);
536 [CLSCompliant (false)]
537 [MethodImplAttribute (MethodImplOptions.InternalCall)]
538 extern public static ulong VolatileRead (ref ulong address);
540 [CLSCompliant (false)]
541 [MethodImplAttribute (MethodImplOptions.InternalCall)]
542 extern public static byte VolatileRead (ref UIntPtr address);
544 [MethodImplAttribute (MethodImplOptions.InternalCall)]
545 extern public static void VolatileWrite (ref byte address, byte value);
547 [MethodImplAttribute (MethodImplOptions.InternalCall)]
548 extern public static void VolatileWrite (ref double address, double value);
550 [MethodImplAttribute (MethodImplOptions.InternalCall)]
551 extern public static void VolatileWrite (ref short address, short value);
553 [MethodImplAttribute (MethodImplOptions.InternalCall)]
554 extern public static void VolatileWrite (ref int address, int value);
556 [MethodImplAttribute (MethodImplOptions.InternalCall)]
557 extern public static void VolatileWrite (ref long address, long value);
559 [MethodImplAttribute (MethodImplOptions.InternalCall)]
560 extern public static void VolatileWrite (ref IntPtr address, IntPtr value);
562 [MethodImplAttribute (MethodImplOptions.InternalCall)]
563 extern public static void VolatileWrite (ref object address, object value);
565 [CLSCompliant(false)]
566 [MethodImplAttribute (MethodImplOptions.InternalCall)]
567 extern public static void VolatileWrite (ref sbyte address, sbyte value);
569 [MethodImplAttribute (MethodImplOptions.InternalCall)]
570 extern public static void VolatileWrite (ref float address, float value);
572 [CLSCompliant (false)]
573 [MethodImplAttribute (MethodImplOptions.InternalCall)]
574 extern public static void VolatileWrite (ref ushort address, ushort value);
576 [CLSCompliant (false)]
577 [MethodImplAttribute (MethodImplOptions.InternalCall)]
578 extern public static void VolatileWrite (ref uint address, uint value);
580 [CLSCompliant (false)]
581 [MethodImplAttribute (MethodImplOptions.InternalCall)]
582 extern public static void VolatileWrite (ref ulong address, ulong value);
584 [CLSCompliant (false)]
585 [MethodImplAttribute (MethodImplOptions.InternalCall)]
586 extern public static void VolatileWrite (ref UIntPtr address, UIntPtr value);