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
21 private CultureInfo current_culture;
24 public static Context CurrentContext {
27 // System.Runtime.Remoting.Context not
34 public static IPrincipal CurrentPrincipal {
37 // System.Security.Principal.IPrincipal
38 // not yet implemented
46 // Looks up the object associated with the current thread
47 [MethodImplAttribute(MethodImplOptions.InternalCall)]
48 private extern static Thread CurrentThread_internal();
50 public static Thread CurrentThread {
52 return(CurrentThread_internal());
56 // Looks up the slot hash for the current thread
57 [MethodImplAttribute(MethodImplOptions.InternalCall)]
58 private extern static Hashtable SlotHash_lookup();
60 // Stores the slot hash for the current thread
61 [MethodImplAttribute(MethodImplOptions.InternalCall)]
62 private extern static void SlotHash_store(Hashtable slothash);
64 private static Hashtable GetTLSSlotHash() {
65 Hashtable slothash=SlotHash_lookup();
67 // Not synchronised, because this is
68 // thread specific anyway.
69 slothash=new Hashtable();
70 SlotHash_store(slothash);
76 public static LocalDataStoreSlot AllocateDataSlot() {
77 LocalDataStoreSlot slot = new LocalDataStoreSlot();
82 // Stores a hash keyed by strings of LocalDataStoreSlot objects
83 static Hashtable datastorehash = Hashtable.Synchronized(new Hashtable());
85 public static LocalDataStoreSlot AllocateNamedDataSlot(string name) {
86 LocalDataStoreSlot slot = (LocalDataStoreSlot)datastorehash[name];
88 // This exception isnt documented (of
89 // course) but .net throws it
90 throw new ArgumentException("Named data slot already added");
93 slot = new LocalDataStoreSlot();
95 datastorehash.Add(name, slot);
100 public static void FreeNamedDataSlot(string name) {
101 LocalDataStoreSlot slot=(LocalDataStoreSlot)datastorehash[name];
104 datastorehash.Remove(slot);
108 public static object GetData(LocalDataStoreSlot slot) {
109 Hashtable slothash=GetTLSSlotHash();
110 return(slothash[slot]);
114 public static AppDomain GetDomain() {
120 public static int GetDomainID() {
125 public static LocalDataStoreSlot GetNamedDataSlot(string name) {
126 LocalDataStoreSlot slot=(LocalDataStoreSlot)datastorehash[name];
129 slot=AllocateNamedDataSlot(name);
136 public static void ResetAbort() {
140 public static void SetData(LocalDataStoreSlot slot,
142 Hashtable slothash=GetTLSSlotHash();
143 slothash.Add(slot, data);
146 [MethodImplAttribute(MethodImplOptions.InternalCall)]
147 private extern static void Sleep_internal(int ms);
149 public static void Sleep(int millisecondsTimeout) {
150 if(millisecondsTimeout<0) {
151 throw new ArgumentException("Negative timeout");
153 Thread thread=CurrentThread;
155 thread.set_state(ThreadState.WaitSleepJoin);
157 Sleep_internal(millisecondsTimeout);
158 thread.clr_state(ThreadState.WaitSleepJoin);
161 public static void Sleep(TimeSpan timeout) {
162 // LAMESPEC: says to throw ArgumentException too
163 if(timeout.Milliseconds < 0 || timeout.Milliseconds > Int32.MaxValue) {
164 throw new ArgumentOutOfRangeException("Timeout out of range");
167 Thread thread=CurrentThread;
169 thread.set_state(ThreadState.WaitSleepJoin);
170 Sleep_internal(timeout.Milliseconds);
171 thread.clr_state(ThreadState.WaitSleepJoin);
174 // stores a thread handle
175 private IntPtr system_thread_handle;
177 // Returns the system thread handle
178 [MethodImplAttribute(MethodImplOptions.InternalCall)]
179 private extern IntPtr Thread_internal(ThreadStart start);
181 public Thread(ThreadStart start) {
183 throw new ArgumentNullException("Null ThreadStart");
186 // This is a two-stage thread launch. Thread_internal
187 // creates the new thread, but blocks it until
188 // Start() is called later.
189 system_thread_handle=Thread_internal(start);
193 public ApartmentState ApartmentState {
196 return(ApartmentState.Unknown);
204 public CultureInfo CurrentCulture {
206 if (current_culture == null)
207 current_culture = new CultureInfo ("");
208 return current_culture;
212 current_culture = value;
217 public CultureInfo CurrentUICulture {
227 public bool IsAlive {
229 // LAMESPEC: is a Stopped or Suspended
231 ThreadState curstate=state;
233 if((curstate & ThreadState.Aborted) != 0 ||
234 (curstate & ThreadState.AbortRequested) != 0 ||
235 (curstate & ThreadState.Unstarted) != 0) {
243 public bool IsBackground {
245 if((state & ThreadState.Background) != 0) {
254 set_state(ThreadState.Background);
256 clr_state(ThreadState.Background);
261 private string thread_name=null;
274 public ThreadPriority Priority {
277 return(ThreadPriority.Lowest);
284 private ThreadState state=ThreadState.Unstarted;
286 public ThreadState ThreadState {
293 public void Abort() {
298 public void Abort(object stateInfo) {
303 public void Interrupt() {
307 // The current thread joins with 'this'. Set ms to 0 to block
308 // until this actually exits.
309 [MethodImplAttribute(MethodImplOptions.InternalCall)]
310 private extern bool Join_internal(int ms, IntPtr handle);
313 if((state & ThreadState.Unstarted) != 0) {
314 throw new ThreadStateException("Thread has not been started");
317 Thread thread=CurrentThread;
319 thread.set_state(ThreadState.WaitSleepJoin);
320 Join_internal(Timeout.Infinite, system_thread_handle);
321 thread.clr_state(ThreadState.WaitSleepJoin);
324 public bool Join(int millisecondsTimeout) {
325 if(millisecondsTimeout<0) {
326 throw new ArgumentException("Timeout less than zero");
328 if((state & ThreadState.Unstarted) != 0) {
329 throw new ThreadStateException("Thread has not been started");
332 Thread thread=CurrentThread;
334 thread.set_state(ThreadState.WaitSleepJoin);
335 bool ret=Join_internal(millisecondsTimeout,
336 system_thread_handle);
337 thread.clr_state(ThreadState.WaitSleepJoin);
342 public bool Join(TimeSpan timeout) {
343 // LAMESPEC: says to throw ArgumentException too
344 if(timeout.Milliseconds < 0 || timeout.Milliseconds > Int32.MaxValue) {
345 throw new ArgumentOutOfRangeException("timeout out of range");
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 bool ret=Join_internal(timeout.Milliseconds,
355 system_thread_handle);
356 thread.clr_state(ThreadState.WaitSleepJoin);
362 public void Resume() {
366 // Launches the thread
367 [MethodImplAttribute(MethodImplOptions.InternalCall)]
368 private extern void Start_internal(IntPtr handle);
370 public void Start() {
371 if((state & ThreadState.Unstarted) == 0) {
372 throw new ThreadStateException("Thread has already been started");
375 // Mark the thread state as Running (which is
376 // all bits cleared). Therefore just remove
378 clr_state(ThreadState.Unstarted);
380 // Launch this thread
381 Start_internal(system_thread_handle);
385 public void Suspend() {
386 if((state & ThreadState.Unstarted) != 0 || !IsAlive) {
387 throw new ThreadStateException("Thread has not been started, or is dead");
390 set_state(ThreadState.SuspendRequested);
391 // FIXME - somehow let the interpreter know that
392 // this thread should now suspend
400 private void set_state(ThreadState set) {
405 private void clr_state(ThreadState clr) {