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]);
122 public static AppDomain GetDomain() {
128 public static int GetDomainID() {
133 public static LocalDataStoreSlot GetNamedDataSlot(string name) {
134 LocalDataStoreSlot slot=(LocalDataStoreSlot)datastorehash[name];
137 slot=AllocateNamedDataSlot(name);
143 [MethodImplAttribute(MethodImplOptions.InternalCall)]
144 public extern static void ResetAbort();
146 public static void SetData(LocalDataStoreSlot slot,
148 Hashtable slothash=GetTLSSlotHash();
150 if(slothash[slot]!=null) {
151 slothash.Remove(slot);
154 slothash.Add(slot, data);
157 [MethodImplAttribute(MethodImplOptions.InternalCall)]
158 private extern static void Sleep_internal(int ms);
160 public static void Sleep(int millisecondsTimeout) {
161 if(millisecondsTimeout<0) {
162 throw new ArgumentException("Negative timeout");
164 Thread thread=CurrentThread;
166 thread.set_state(ThreadState.WaitSleepJoin);
168 Sleep_internal(millisecondsTimeout);
169 thread.clr_state(ThreadState.WaitSleepJoin);
172 public static void Sleep(TimeSpan timeout) {
173 // LAMESPEC: says to throw ArgumentException too
174 if(timeout.Milliseconds < 0 || timeout.Milliseconds > Int32.MaxValue) {
175 throw new ArgumentOutOfRangeException("Timeout out of range");
178 Thread thread=CurrentThread;
180 thread.set_state(ThreadState.WaitSleepJoin);
181 Sleep_internal(timeout.Milliseconds);
182 thread.clr_state(ThreadState.WaitSleepJoin);
185 // Returns the system thread handle
186 [MethodImplAttribute(MethodImplOptions.InternalCall)]
187 private extern IntPtr Thread_internal(ThreadStart start);
189 public Thread(ThreadStart start) {
191 throw new ArgumentNullException("Null ThreadStart");
194 // This is a two-stage thread launch. Thread_internal
195 // creates the new thread, but blocks it until
196 // Start() is called later.
197 system_thread_handle=Thread_internal(start);
199 // Should throw an exception here if
200 // Thread_internal returns NULL
204 public ApartmentState ApartmentState {
207 return(ApartmentState.Unknown);
215 public CultureInfo CurrentCulture {
217 if (current_culture == null)
218 current_culture = new CultureInfo ("");
219 return current_culture;
223 current_culture = value;
228 public CultureInfo CurrentUICulture {
231 return(CurrentCulture);
236 CurrentCulture=value;
240 public bool IsThreadPoolThread {
242 return IsThreadPoolThreadInternal;
246 internal bool IsThreadPoolThreadInternal {
248 return threadpool_thread;
251 threadpool_thread = value;
255 public bool IsAlive {
257 // LAMESPEC: is a Stopped or Suspended
259 ThreadState curstate=state;
261 if((curstate & ThreadState.Aborted) != 0 ||
262 (curstate & ThreadState.AbortRequested) != 0 ||
263 (curstate & ThreadState.Unstarted) != 0) {
271 public bool IsBackground {
273 if((state & ThreadState.Background) != 0) {
282 set_state(ThreadState.Background);
284 clr_state(ThreadState.Background);
289 private string thread_name=null;
302 public ThreadPriority Priority {
305 return(ThreadPriority.Lowest);
312 public ThreadState ThreadState {
318 public void Abort() {
322 [MethodImplAttribute(MethodImplOptions.InternalCall)]
323 public extern void Abort (object stateInfo);
326 public void Interrupt() {
330 // The current thread joins with 'this'. Set ms to 0 to block
331 // until this actually exits.
332 [MethodImplAttribute(MethodImplOptions.InternalCall)]
333 private extern bool Join_internal(int ms, IntPtr handle);
336 if((state & ThreadState.Unstarted) != 0) {
337 throw new ThreadStateException("Thread has not been started");
340 Thread thread=CurrentThread;
342 thread.set_state(ThreadState.WaitSleepJoin);
343 Join_internal(Timeout.Infinite, system_thread_handle);
344 thread.clr_state(ThreadState.WaitSleepJoin);
347 public bool Join(int millisecondsTimeout) {
348 if(millisecondsTimeout<0) {
349 throw new ArgumentException("Timeout less than zero");
351 if((state & ThreadState.Unstarted) != 0) {
352 throw new ThreadStateException("Thread has not been started");
355 Thread thread=CurrentThread;
357 thread.set_state(ThreadState.WaitSleepJoin);
358 bool ret=Join_internal(millisecondsTimeout,
359 system_thread_handle);
360 thread.clr_state(ThreadState.WaitSleepJoin);
365 public bool Join(TimeSpan timeout) {
366 // LAMESPEC: says to throw ArgumentException too
367 if(timeout.Milliseconds < 0 || timeout.Milliseconds > Int32.MaxValue) {
368 throw new ArgumentOutOfRangeException("timeout out of range");
370 if((state & ThreadState.Unstarted) != 0) {
371 throw new ThreadStateException("Thread has not been started");
374 Thread thread=CurrentThread;
376 thread.set_state(ThreadState.WaitSleepJoin);
377 bool ret=Join_internal(timeout.Milliseconds,
378 system_thread_handle);
379 thread.clr_state(ThreadState.WaitSleepJoin);
385 public void Resume() {
389 // Launches the thread
390 [MethodImplAttribute(MethodImplOptions.InternalCall)]
391 private extern void Start_internal(IntPtr handle);
393 public void Start() {
394 if((state & ThreadState.Unstarted) == 0) {
395 throw new ThreadStateException("Thread has already been started");
398 // Mark the thread state as Running (which is
399 // all bits cleared). Therefore just remove
401 clr_state(ThreadState.Unstarted);
403 // Launch this thread
404 Start_internal(system_thread_handle);
408 public void Suspend() {
409 if((state & ThreadState.Unstarted) != 0 || !IsAlive) {
410 throw new ThreadStateException("Thread has not been started, or is dead");
413 set_state(ThreadState.SuspendRequested);
414 // FIXME - somehow let the interpreter know that
415 // this thread should now suspend
418 // Closes the system thread handle
419 [MethodImplAttribute(MethodImplOptions.InternalCall)]
420 private extern void Thread_free_internal(IntPtr handle);
423 // Free up the handle
424 Thread_free_internal(system_thread_handle);
427 private void set_state(ThreadState set) {
432 private void clr_state(ThreadState clr) {