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 = Hashtable.Synchronized(new Hashtable());
93 public static LocalDataStoreSlot AllocateNamedDataSlot(string name) {
94 LocalDataStoreSlot slot = (LocalDataStoreSlot)datastorehash[name];
96 // This exception isnt documented (of
97 // course) but .net throws it
98 throw new ArgumentException("Named data slot already added");
101 slot = new LocalDataStoreSlot();
103 datastorehash.Add(name, slot);
108 public static void FreeNamedDataSlot(string name) {
109 LocalDataStoreSlot slot=(LocalDataStoreSlot)datastorehash[name];
112 datastorehash.Remove(slot);
116 public static object GetData(LocalDataStoreSlot slot) {
117 Hashtable slothash=GetTLSSlotHash();
118 return(slothash[slot]);
121 public static AppDomain GetDomain() {
122 return AppDomain.CurrentDomain;
125 [MethodImplAttribute(MethodImplOptions.InternalCall)]
126 public extern static int GetDomainID();
128 public static LocalDataStoreSlot GetNamedDataSlot(string name) {
129 LocalDataStoreSlot slot=(LocalDataStoreSlot)datastorehash[name];
132 slot=AllocateNamedDataSlot(name);
138 [MethodImplAttribute(MethodImplOptions.InternalCall)]
139 public extern static void ResetAbort();
141 public static void SetData(LocalDataStoreSlot slot,
143 Hashtable slothash=GetTLSSlotHash();
145 if(slothash[slot]!=null) {
146 slothash.Remove(slot);
149 slothash.Add(slot, data);
152 [MethodImplAttribute(MethodImplOptions.InternalCall)]
153 private extern static void Sleep_internal(int ms);
155 public static void Sleep(int millisecondsTimeout) {
156 if(millisecondsTimeout<0) {
157 throw new ArgumentException("Negative timeout");
159 Thread thread=CurrentThread;
161 thread.set_state(ThreadState.WaitSleepJoin);
163 Sleep_internal(millisecondsTimeout);
164 thread.clr_state(ThreadState.WaitSleepJoin);
167 public static void Sleep(TimeSpan timeout) {
168 // LAMESPEC: says to throw ArgumentException too
169 if(timeout.Milliseconds < 0 || timeout.Milliseconds > Int32.MaxValue) {
170 throw new ArgumentOutOfRangeException("Timeout out of range");
173 Thread thread=CurrentThread;
175 thread.set_state(ThreadState.WaitSleepJoin);
176 Sleep_internal(timeout.Milliseconds);
177 thread.clr_state(ThreadState.WaitSleepJoin);
180 // Returns the system thread handle
181 [MethodImplAttribute(MethodImplOptions.InternalCall)]
182 private extern IntPtr Thread_internal(ThreadStart start);
184 public Thread(ThreadStart start) {
186 throw new ArgumentNullException("Null ThreadStart");
189 // This is a two-stage thread launch. Thread_internal
190 // creates the new thread, but blocks it until
191 // Start() is called later.
192 system_thread_handle=Thread_internal(start);
194 // Should throw an exception here if
195 // Thread_internal returns NULL
199 public ApartmentState ApartmentState {
202 return(ApartmentState.Unknown);
210 public CultureInfo CurrentCulture {
212 if (current_culture == null)
213 current_culture = new CultureInfo ("");
214 return current_culture;
218 current_culture = value;
223 public CultureInfo CurrentUICulture {
226 return(CurrentCulture);
231 CurrentCulture=value;
235 public bool IsThreadPoolThread {
237 return IsThreadPoolThreadInternal;
241 internal bool IsThreadPoolThreadInternal {
243 return threadpool_thread;
246 threadpool_thread = value;
250 public bool IsAlive {
252 // LAMESPEC: is a Stopped or Suspended
254 ThreadState curstate=state;
256 if((curstate & ThreadState.Aborted) != 0 ||
257 (curstate & ThreadState.AbortRequested) != 0 ||
258 (curstate & ThreadState.Unstarted) != 0) {
266 public bool IsBackground {
268 if((state & ThreadState.Background) != 0) {
277 set_state(ThreadState.Background);
279 clr_state(ThreadState.Background);
284 private string thread_name=null;
297 public ThreadPriority Priority {
300 return(ThreadPriority.Lowest);
307 public ThreadState ThreadState {
313 public void Abort() {
317 [MethodImplAttribute(MethodImplOptions.InternalCall)]
318 public extern void Abort (object stateInfo);
321 public void Interrupt() {
325 // The current thread joins with 'this'. Set ms to 0 to block
326 // until this actually exits.
327 [MethodImplAttribute(MethodImplOptions.InternalCall)]
328 private extern bool Join_internal(int ms, IntPtr handle);
331 if((state & ThreadState.Unstarted) != 0) {
332 throw new ThreadStateException("Thread has not been started");
335 Thread thread=CurrentThread;
337 thread.set_state(ThreadState.WaitSleepJoin);
338 Join_internal(Timeout.Infinite, system_thread_handle);
339 thread.clr_state(ThreadState.WaitSleepJoin);
342 public bool Join(int millisecondsTimeout) {
343 if(millisecondsTimeout<0) {
344 throw new ArgumentException("Timeout less than zero");
346 if((state & ThreadState.Unstarted) != 0) {
347 throw new ThreadStateException("Thread has not been started");
350 Thread thread=CurrentThread;
352 thread.set_state(ThreadState.WaitSleepJoin);
353 bool ret=Join_internal(millisecondsTimeout,
354 system_thread_handle);
355 thread.clr_state(ThreadState.WaitSleepJoin);
360 public bool Join(TimeSpan timeout) {
361 // LAMESPEC: says to throw ArgumentException too
362 if(timeout.Milliseconds < 0 || timeout.Milliseconds > Int32.MaxValue) {
363 throw new ArgumentOutOfRangeException("timeout out of range");
365 if((state & ThreadState.Unstarted) != 0) {
366 throw new ThreadStateException("Thread has not been started");
369 Thread thread=CurrentThread;
371 thread.set_state(ThreadState.WaitSleepJoin);
372 bool ret=Join_internal(timeout.Milliseconds,
373 system_thread_handle);
374 thread.clr_state(ThreadState.WaitSleepJoin);
380 public void Resume() {
384 // Launches the thread
385 [MethodImplAttribute(MethodImplOptions.InternalCall)]
386 private extern void Start_internal(IntPtr handle);
388 public void Start() {
389 if((state & ThreadState.Unstarted) == 0) {
390 throw new ThreadStateException("Thread has already been started");
393 // Mark the thread state as Running (which is
394 // all bits cleared). Therefore just remove
396 clr_state(ThreadState.Unstarted);
398 // Launch this thread
399 Start_internal(system_thread_handle);
403 public void Suspend() {
404 if((state & ThreadState.Unstarted) != 0 || !IsAlive) {
405 throw new ThreadStateException("Thread has not been started, or is dead");
408 set_state(ThreadState.SuspendRequested);
409 // FIXME - somehow let the interpreter know that
410 // this thread should now suspend
413 // Closes the system thread handle
414 [MethodImplAttribute(MethodImplOptions.InternalCall)]
415 private extern void Thread_free_internal(IntPtr handle);
418 // Free up the handle
419 Thread_free_internal(system_thread_handle);
422 private void set_state(ThreadState set) {
427 private void clr_state(ThreadState clr) {