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 = false;
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;
32 public static Context CurrentContext {
35 // System.Runtime.Remoting.Context not
42 public static IPrincipal CurrentPrincipal {
45 // System.Security.Principal.IPrincipal
46 // not yet implemented
54 // Looks up the object associated with the current thread
55 [MethodImplAttribute(MethodImplOptions.InternalCall)]
56 private extern static Thread CurrentThread_internal();
58 public static Thread CurrentThread {
60 return(CurrentThread_internal());
64 // Looks up the slot hash for the current thread
65 [MethodImplAttribute(MethodImplOptions.InternalCall)]
66 private extern static Hashtable SlotHash_lookup();
68 // Stores the slot hash for the current thread
69 [MethodImplAttribute(MethodImplOptions.InternalCall)]
70 private extern static void SlotHash_store(Hashtable slothash);
72 private static Hashtable GetTLSSlotHash() {
73 Hashtable slothash=SlotHash_lookup();
75 // Not synchronised, because this is
76 // thread specific anyway.
77 slothash=new Hashtable();
78 SlotHash_store(slothash);
84 public static LocalDataStoreSlot AllocateDataSlot() {
85 LocalDataStoreSlot slot = new LocalDataStoreSlot();
90 // Stores a hash keyed by strings of LocalDataStoreSlot objects
91 static Hashtable datastorehash;
93 private static void InitDataStoreHash () {
94 lock (typeof (Thread)) {
95 if (datastorehash == null) {
96 datastorehash = Hashtable.Synchronized(new Hashtable());
101 public static LocalDataStoreSlot AllocateNamedDataSlot(string name) {
102 if (datastorehash == null)
103 InitDataStoreHash ();
104 LocalDataStoreSlot slot = (LocalDataStoreSlot)datastorehash[name];
106 // This exception isnt documented (of
107 // course) but .net throws it
108 throw new ArgumentException("Named data slot already added");
111 slot = new LocalDataStoreSlot();
113 datastorehash.Add(name, slot);
118 public static void FreeNamedDataSlot(string name) {
119 if (datastorehash == null)
120 InitDataStoreHash ();
121 LocalDataStoreSlot slot=(LocalDataStoreSlot)datastorehash[name];
124 datastorehash.Remove(slot);
128 public static object GetData(LocalDataStoreSlot slot) {
129 Hashtable slothash=GetTLSSlotHash();
130 return(slothash[slot]);
133 public static AppDomain GetDomain() {
134 return AppDomain.CurrentDomain;
137 [MethodImplAttribute(MethodImplOptions.InternalCall)]
138 public extern static int GetDomainID();
140 public static LocalDataStoreSlot GetNamedDataSlot(string name) {
141 if (datastorehash == null)
142 InitDataStoreHash ();
143 LocalDataStoreSlot slot=(LocalDataStoreSlot)datastorehash[name];
146 slot=AllocateNamedDataSlot(name);
152 [MethodImplAttribute(MethodImplOptions.InternalCall)]
153 public extern static void ResetAbort();
155 public static void SetData(LocalDataStoreSlot slot,
157 Hashtable slothash=GetTLSSlotHash();
159 if(slothash[slot]!=null) {
160 slothash.Remove(slot);
163 slothash.Add(slot, data);
166 [MethodImplAttribute(MethodImplOptions.InternalCall)]
167 private extern static void Sleep_internal(int ms);
169 public static void Sleep(int millisecondsTimeout) {
170 if(millisecondsTimeout<0) {
171 throw new ArgumentException("Negative timeout");
173 Thread thread=CurrentThread;
175 thread.set_state(ThreadState.WaitSleepJoin);
177 Sleep_internal(millisecondsTimeout);
178 thread.clr_state(ThreadState.WaitSleepJoin);
181 public static void Sleep(TimeSpan timeout) {
182 // LAMESPEC: says to throw ArgumentException too
183 int ms=Convert.ToInt32(timeout.TotalMilliseconds);
185 if(ms < 0 || ms > Int32.MaxValue) {
186 throw new ArgumentOutOfRangeException("Timeout out of range");
189 Thread thread=CurrentThread;
191 thread.set_state(ThreadState.WaitSleepJoin);
193 thread.clr_state(ThreadState.WaitSleepJoin);
196 // Returns the system thread handle
197 [MethodImplAttribute(MethodImplOptions.InternalCall)]
198 private extern IntPtr Thread_internal(ThreadStart start);
200 public Thread(ThreadStart start) {
202 throw new ArgumentNullException("Null ThreadStart");
205 // This is a two-stage thread launch. Thread_internal
206 // creates the new thread, but blocks it until
207 // Start() is called later.
208 system_thread_handle=Thread_internal(start);
210 // Should throw an exception here if
211 // Thread_internal returns NULL
215 public ApartmentState ApartmentState {
218 return(ApartmentState.Unknown);
226 public CultureInfo CurrentCulture {
228 if (current_culture == null)
229 current_culture = new CultureInfo ("");
230 return current_culture;
234 current_culture = value;
239 public CultureInfo CurrentUICulture {
242 return(CurrentCulture);
247 CurrentCulture=value;
251 public bool IsThreadPoolThread {
253 return IsThreadPoolThreadInternal;
257 internal bool IsThreadPoolThreadInternal {
259 return threadpool_thread;
262 threadpool_thread = value;
266 public bool IsAlive {
268 // LAMESPEC: is a Stopped or Suspended
270 ThreadState curstate=state;
272 if((curstate & ThreadState.Aborted) != 0 ||
273 (curstate & ThreadState.AbortRequested) != 0 ||
274 (curstate & ThreadState.Unstarted) != 0) {
282 public bool IsBackground {
284 if((state & ThreadState.Background) != 0) {
293 set_state(ThreadState.Background);
295 clr_state(ThreadState.Background);
300 private string thread_name=null;
313 public ThreadPriority Priority {
316 return(ThreadPriority.Lowest);
323 public ThreadState ThreadState {
329 public void Abort() {
333 [MethodImplAttribute(MethodImplOptions.InternalCall)]
334 public extern void Abort (object stateInfo);
337 public void Interrupt() {
341 // The current thread joins with 'this'. Set ms to 0 to block
342 // until this actually exits.
343 [MethodImplAttribute(MethodImplOptions.InternalCall)]
344 private extern bool Join_internal(int ms, IntPtr handle);
347 if((state & ThreadState.Unstarted) != 0) {
348 throw new ThreadStateException("Thread has not been started");
351 Thread thread=CurrentThread;
353 thread.set_state(ThreadState.WaitSleepJoin);
354 Join_internal(Timeout.Infinite, system_thread_handle);
355 thread.clr_state(ThreadState.WaitSleepJoin);
358 public bool Join(int millisecondsTimeout) {
359 if(millisecondsTimeout<0) {
360 throw new ArgumentException("Timeout less than zero");
362 if((state & ThreadState.Unstarted) != 0) {
363 throw new ThreadStateException("Thread has not been started");
366 Thread thread=CurrentThread;
368 thread.set_state(ThreadState.WaitSleepJoin);
369 bool ret=Join_internal(millisecondsTimeout,
370 system_thread_handle);
371 thread.clr_state(ThreadState.WaitSleepJoin);
376 public bool Join(TimeSpan timeout) {
377 // LAMESPEC: says to throw ArgumentException too
378 int ms=Convert.ToInt32(timeout.TotalMilliseconds);
380 if(ms < 0 || ms > Int32.MaxValue) {
381 throw new ArgumentOutOfRangeException("timeout out of range");
383 if((state & ThreadState.Unstarted) != 0) {
384 throw new ThreadStateException("Thread has not been started");
387 Thread thread=CurrentThread;
389 thread.set_state(ThreadState.WaitSleepJoin);
390 bool ret=Join_internal(ms, system_thread_handle);
391 thread.clr_state(ThreadState.WaitSleepJoin);
397 public void Resume() {
401 // Launches the thread
402 [MethodImplAttribute(MethodImplOptions.InternalCall)]
403 private extern void Start_internal(IntPtr handle);
405 public void Start() {
406 if((state & ThreadState.Unstarted) == 0) {
407 throw new ThreadStateException("Thread has already been started");
410 // Mark the thread state as Running (which is
411 // all bits cleared). Therefore just remove
413 clr_state(ThreadState.Unstarted);
415 // Launch this thread
416 Start_internal(system_thread_handle);
420 public void Suspend() {
421 if((state & ThreadState.Unstarted) != 0 || !IsAlive) {
422 throw new ThreadStateException("Thread has not been started, or is dead");
425 set_state(ThreadState.SuspendRequested);
426 // FIXME - somehow let the interpreter know that
427 // this thread should now suspend
430 // Closes the system thread handle
431 [MethodImplAttribute(MethodImplOptions.InternalCall)]
432 private extern void Thread_free_internal(IntPtr handle);
435 // Free up the handle
436 Thread_free_internal(system_thread_handle);
439 private void set_state(ThreadState set) {
444 private void clr_state(ThreadState clr) {