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 public static Context CurrentContext {
24 // System.Runtime.Remoting.Context not
31 public static IPrincipal CurrentPrincipal {
34 // System.Security.Principal.IPrincipal
35 // not yet implemented
43 // Looks up the object associated with the current thread
44 [MethodImplAttribute(MethodImplOptions.InternalCall)]
45 private extern static Thread CurrentThread_internal();
47 public static Thread CurrentThread {
49 return(CurrentThread_internal());
53 // Looks up the slot hash for the current thread
54 [MethodImplAttribute(MethodImplOptions.InternalCall)]
55 private extern static Hashtable SlotHash_lookup();
57 // Stores the slot hash for the current thread
58 [MethodImplAttribute(MethodImplOptions.InternalCall)]
59 private extern static void SlotHash_store(Hashtable slothash);
61 private static Hashtable GetTLSSlotHash() {
62 Hashtable slothash=SlotHash_lookup();
64 // Not synchronised, because this is
65 // thread specific anyway.
66 slothash=new Hashtable();
67 SlotHash_store(slothash);
73 public static LocalDataStoreSlot AllocateDataSlot() {
74 LocalDataStoreSlot slot = new LocalDataStoreSlot();
79 // Stores a hash keyed by strings of LocalDataStoreSlot objects
80 static Hashtable datastorehash = Hashtable.Synchronized(new Hashtable());
82 public static LocalDataStoreSlot AllocateNamedDataSlot(string name) {
83 LocalDataStoreSlot slot = (LocalDataStoreSlot)datastorehash[name];
85 // This exception isnt documented (of
86 // course) but .net throws it
87 throw new ArgumentException("Named data slot already added");
90 slot = new LocalDataStoreSlot();
92 datastorehash.Add(name, slot);
97 public static void FreeNamedDataSlot(string name) {
98 LocalDataStoreSlot slot=(LocalDataStoreSlot)datastorehash[name];
101 datastorehash.Remove(slot);
105 public static object GetData(LocalDataStoreSlot slot) {
106 Hashtable slothash=GetTLSSlotHash();
107 return(slothash[slot]);
111 public static AppDomain GetDomain() {
117 public static int GetDomainID() {
122 public static LocalDataStoreSlot GetNamedDataSlot(string name) {
123 LocalDataStoreSlot slot=(LocalDataStoreSlot)datastorehash[name];
126 slot=AllocateNamedDataSlot(name);
133 public static void ResetAbort() {
137 public static void SetData(LocalDataStoreSlot slot,
139 Hashtable slothash=GetTLSSlotHash();
140 slothash.Add(slot, data);
143 [MethodImplAttribute(MethodImplOptions.InternalCall)]
144 private extern static void Sleep_internal(int ms);
146 public static void Sleep(int millisecondsTimeout) {
147 if(millisecondsTimeout<0) {
148 throw new ArgumentException("Negative timeout");
150 Thread thread=CurrentThread;
152 thread.set_state(ThreadState.WaitSleepJoin);
154 Sleep_internal(millisecondsTimeout);
155 thread.clr_state(ThreadState.WaitSleepJoin);
158 public static void Sleep(TimeSpan timeout) {
159 // LAMESPEC: says to throw ArgumentException too
160 if(timeout.Milliseconds < 0 || timeout.Milliseconds > Int32.MaxValue) {
161 throw new ArgumentOutOfRangeException("Timeout out of range");
164 Thread thread=CurrentThread;
166 thread.set_state(ThreadState.WaitSleepJoin);
167 Sleep_internal(timeout.Milliseconds);
168 thread.clr_state(ThreadState.WaitSleepJoin);
171 // stores a thread handle
172 private IntPtr system_thread_handle;
174 // Returns the system thread handle
175 [MethodImplAttribute(MethodImplOptions.InternalCall)]
176 private extern IntPtr Thread_internal(ThreadStart start);
178 public Thread(ThreadStart start) {
180 throw new ArgumentNullException("Null ThreadStart");
183 // This is a two-stage thread launch. Thread_internal
184 // creates the new thread, but blocks it until
185 // Start() is called later.
186 system_thread_handle=Thread_internal(start);
190 public ApartmentState ApartmentState {
193 return(ApartmentState.Unknown);
201 public CultureInfo CurrentCulture {
212 public CultureInfo CurrentUICulture {
222 public bool IsAlive {
224 // LAMESPEC: is a Stopped or Suspended
226 ThreadState curstate=state;
228 if((curstate & ThreadState.Aborted) != 0 ||
229 (curstate & ThreadState.AbortRequested) != 0 ||
230 (curstate & ThreadState.Unstarted) != 0) {
238 public bool IsBackground {
240 if((state & ThreadState.Background) != 0) {
249 set_state(ThreadState.Background);
251 clr_state(ThreadState.Background);
256 private string thread_name=null;
269 public ThreadPriority Priority {
272 return(ThreadPriority.Lowest);
279 private ThreadState state=ThreadState.Unstarted;
281 public ThreadState ThreadState {
288 public void Abort() {
293 public void Abort(object stateInfo) {
298 public void Interrupt() {
302 // The current thread joins with 'this'. Set ms to 0 to block
303 // until this actually exits.
304 [MethodImplAttribute(MethodImplOptions.InternalCall)]
305 private extern bool Join_internal(int ms, IntPtr handle);
308 if((state & ThreadState.Unstarted) != 0) {
309 throw new ThreadStateException("Thread has not been started");
312 Thread thread=CurrentThread;
314 thread.set_state(ThreadState.WaitSleepJoin);
315 Join_internal(0, system_thread_handle);
316 thread.clr_state(ThreadState.WaitSleepJoin);
319 public bool Join(int millisecondsTimeout) {
320 if(millisecondsTimeout<0) {
321 throw new ArgumentException("Timeout less than zero");
323 if((state & ThreadState.Unstarted) != 0) {
324 throw new ThreadStateException("Thread has not been started");
327 Thread thread=CurrentThread;
329 thread.set_state(ThreadState.WaitSleepJoin);
330 bool ret=Join_internal(millisecondsTimeout,
331 system_thread_handle);
332 thread.clr_state(ThreadState.WaitSleepJoin);
337 public bool Join(TimeSpan timeout) {
338 // LAMESPEC: says to throw ArgumentException too
339 if(timeout.Milliseconds < 0 || timeout.Milliseconds > Int32.MaxValue) {
340 throw new ArgumentOutOfRangeException("timeout out of range");
342 if((state & ThreadState.Unstarted) != 0) {
343 throw new ThreadStateException("Thread has not been started");
346 Thread thread=CurrentThread;
348 thread.set_state(ThreadState.WaitSleepJoin);
349 bool ret=Join_internal(timeout.Milliseconds,
350 system_thread_handle);
351 thread.clr_state(ThreadState.WaitSleepJoin);
357 public void Resume() {
361 // Launches the thread
362 [MethodImplAttribute(MethodImplOptions.InternalCall)]
363 private extern void Start_internal(IntPtr handle);
365 public void Start() {
366 if((state & ThreadState.Unstarted) == 0) {
367 throw new ThreadStateException("Thread has already been started");
370 // Mark the thread state as Running (which is
371 // all bits cleared). Therefore just remove
373 clr_state(ThreadState.Unstarted);
375 // Launch this thread
376 Start_internal(system_thread_handle);
380 public void Suspend() {
381 if((state & ThreadState.Unstarted) != 0 || !IsAlive) {
382 throw new ThreadStateException("Thread has not been started, or is dead");
385 set_state(ThreadState.SuspendRequested);
386 // FIXME - somehow let the interpreter know that
387 // this thread should now suspend
395 private void set_state(ThreadState set) {
400 private void clr_state(ThreadState clr) {