(DISTFILES): Comment out a few missing files.
[mono-project.git] / mcs / class / corlib / System.Threading / Thread.cs
blob942707e92cc1ff21203ae784f311e4fba20d23dc
1 //
2 // System.Threading.Thread.cs
3 //
4 // Author:
5 // Dick Porter (dick@ximian.com)
6 //
7 // (C) Ximian, Inc. http://www.ximian.com
8 // Copyright (C) 2004 Novell (http://www.novell.com)
9 //
12 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 //
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 //
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System.Runtime.Remoting.Contexts;
35 using System.Security.Permissions;
36 using System.Security.Principal;
37 using System.Globalization;
38 using System.Runtime.CompilerServices;
39 using System.Collections;
41 #if NET_2_0
42 using System.Runtime.ConstrainedExecution;
43 using System.Runtime.InteropServices;
44 #endif
46 namespace System.Threading
48 public sealed class Thread
50 #region Sync with object.h
51 // stores a thread handle
52 private IntPtr system_thread_handle;
54 private CultureInfo current_culture;
55 private CultureInfo current_ui_culture;
56 private bool threadpool_thread;
57 /* accessed only from unmanaged code */
58 private IntPtr name;
59 private int name_len;
60 private ThreadState state = ThreadState.Unstarted;
61 private object abort_exc;
62 internal object abort_state;
63 /* thread_id is only accessed from unmanaged code */
64 private int thread_id;
66 /* start_notify is used by the runtime to signal that Start()
67 * is ok to return
69 private IntPtr start_notify;
70 private IntPtr stack_ptr;
71 private IntPtr static_data;
72 private IntPtr jit_data;
73 private IntPtr lock_data;
74 private IntPtr appdomain_refs;
75 private bool interruption_requested;
76 private IntPtr suspend_event;
77 private IntPtr resume_event;
78 private object synch_lock = new Object();
79 #endregion
81 private ThreadStart threadstart;
82 private string thread_name=null;
84 private IPrincipal _principal;
86 public static Context CurrentContext {
87 get {
88 return(AppDomain.InternalGetContext ());
92 public static IPrincipal CurrentPrincipal {
93 get {
94 IPrincipal p = null;
95 Thread th = CurrentThread;
96 lock (th) {
97 p = th._principal;
98 if (p == null) {
99 p = GetDomain ().DefaultPrincipal;
100 th._principal = p;
103 return p;
105 [SecurityPermission (SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPolicy)]
106 set {
107 CurrentThread._principal = value;
111 // Looks up the object associated with the current thread
112 [MethodImplAttribute(MethodImplOptions.InternalCall)]
113 private extern static Thread CurrentThread_internal();
115 public static Thread CurrentThread {
116 #if NET_2_0
117 [ReliabilityContract (Consistency.WillNotCorruptState, CER.MayFail)]
118 #endif
119 get {
120 return(CurrentThread_internal());
124 internal static int CurrentThreadId {
125 get {
126 return CurrentThread.thread_id;
130 // Looks up the slot hash for the current thread
131 [MethodImplAttribute(MethodImplOptions.InternalCall)]
132 private extern static Hashtable SlotHash_lookup();
134 // Stores the slot hash for the current thread
135 [MethodImplAttribute(MethodImplOptions.InternalCall)]
136 private extern static void SlotHash_store(Hashtable slothash);
138 private static Hashtable GetTLSSlotHash() {
139 Hashtable slothash=SlotHash_lookup();
140 if(slothash==null) {
141 // Not synchronised, because this is
142 // thread specific anyway.
143 slothash=new Hashtable();
144 SlotHash_store(slothash);
147 return(slothash);
150 internal static object ResetDataStoreStatus () {
151 Hashtable slothash=SlotHash_lookup();
152 SlotHash_store(null);
153 return slothash;
156 internal static void RestoreDataStoreStatus (object data) {
157 SlotHash_store((Hashtable)data);
160 public static LocalDataStoreSlot AllocateDataSlot() {
161 LocalDataStoreSlot slot = new LocalDataStoreSlot();
163 return(slot);
166 // Stores a hash keyed by strings of LocalDataStoreSlot objects
167 static Hashtable datastorehash;
168 private static object datastore_lock = new object ();
170 private static void InitDataStoreHash () {
171 lock (datastore_lock) {
172 if (datastorehash == null) {
173 datastorehash = Hashtable.Synchronized(new Hashtable());
178 public static LocalDataStoreSlot AllocateNamedDataSlot(string name) {
179 lock (datastore_lock) {
180 if (datastorehash == null)
181 InitDataStoreHash ();
182 LocalDataStoreSlot slot = (LocalDataStoreSlot)datastorehash[name];
183 if(slot!=null) {
184 // This exception isnt documented (of
185 // course) but .net throws it
186 throw new ArgumentException("Named data slot already added");
189 slot = new LocalDataStoreSlot();
191 datastorehash.Add(name, slot);
193 return(slot);
197 public static void FreeNamedDataSlot(string name) {
198 lock (datastore_lock) {
199 if (datastorehash == null)
200 InitDataStoreHash ();
201 LocalDataStoreSlot slot=(LocalDataStoreSlot)datastorehash[name];
203 if(slot!=null) {
204 datastorehash.Remove(slot);
209 public static object GetData(LocalDataStoreSlot slot) {
210 Hashtable slothash=GetTLSSlotHash();
211 return(slothash[slot]);
214 public static AppDomain GetDomain() {
215 return AppDomain.CurrentDomain;
218 [MethodImplAttribute(MethodImplOptions.InternalCall)]
219 public extern static int GetDomainID();
221 public static LocalDataStoreSlot GetNamedDataSlot(string name) {
222 lock (datastore_lock) {
223 if (datastorehash == null)
224 InitDataStoreHash ();
225 LocalDataStoreSlot slot=(LocalDataStoreSlot)datastorehash[name];
227 if(slot==null) {
228 slot=AllocateNamedDataSlot(name);
231 return(slot);
235 [MethodImplAttribute(MethodImplOptions.InternalCall)]
236 private extern static void ResetAbort_internal();
238 public static void ResetAbort()
240 ResetAbort_internal();
244 public static void SetData(LocalDataStoreSlot slot,
245 object data) {
246 Hashtable slothash=GetTLSSlotHash();
248 if(slothash.Contains(slot)) {
249 slothash.Remove(slot);
252 slothash.Add(slot, data);
255 [MethodImplAttribute(MethodImplOptions.InternalCall)]
256 private extern static void Sleep_internal(int ms);
258 public static void Sleep(int millisecondsTimeout) {
259 if((millisecondsTimeout<0) && (millisecondsTimeout != Timeout.Infinite)) {
260 throw new ArgumentException("Negative timeout");
262 Thread thread=CurrentThread;
263 Sleep_internal(millisecondsTimeout);
266 public static void Sleep(TimeSpan timeout) {
267 // LAMESPEC: says to throw ArgumentException too
268 int ms=Convert.ToInt32(timeout.TotalMilliseconds);
270 if(ms < 0 || ms > Int32.MaxValue) {
271 throw new ArgumentOutOfRangeException("Timeout out of range");
274 Thread thread=CurrentThread;
275 Sleep_internal(ms);
278 // Returns the system thread handle
279 [MethodImplAttribute(MethodImplOptions.InternalCall)]
280 private extern IntPtr Thread_internal(ThreadStart start);
282 public Thread(ThreadStart start) {
283 if(start==null) {
284 throw new ArgumentNullException("Null ThreadStart");
286 threadstart=start;
289 [MonoTODO]
290 #if NET_2_0
291 [Obsolete ("")]
292 #endif
293 public ApartmentState ApartmentState {
294 get {
295 return(ApartmentState.Unknown);
298 set {
302 [MethodImplAttribute (MethodImplOptions.InternalCall)]
303 private static extern int current_lcid ();
305 /* If the current_lcid() isn't known by CultureInfo,
306 * it will throw an exception which may cause
307 * String.Concat to try and recursively look up the
308 * CurrentCulture, which will throw an exception, etc.
309 * Use a boolean to short-circuit this scenario.
311 private static bool in_currentculture=false;
313 public CultureInfo CurrentCulture {
314 get {
315 if (current_culture == null) {
316 lock (typeof (Thread)) {
317 if(current_culture==null) {
318 if(in_currentculture==true) {
319 /* Bail out */
320 current_culture = CultureInfo.InvariantCulture;
321 } else {
322 in_currentculture=true;
324 current_culture = CultureInfo.ConstructCurrentCulture ();
328 in_currentculture=false;
332 return(current_culture);
335 set {
336 current_culture = value;
340 public CultureInfo CurrentUICulture {
341 get {
342 if (current_ui_culture == null) {
343 lock (synch_lock) {
344 if(current_ui_culture==null) {
345 /* We don't
346 * distinguish
347 * between
348 * System and
349 * UI cultures
351 current_ui_culture = CultureInfo.ConstructCurrentUICulture ();
356 return(current_ui_culture);
359 set {
360 current_ui_culture = value;
364 public bool IsThreadPoolThread {
365 get {
366 return IsThreadPoolThreadInternal;
370 internal bool IsThreadPoolThreadInternal {
371 get {
372 return threadpool_thread;
374 set {
375 threadpool_thread = value;
379 public bool IsAlive {
380 get {
381 ThreadState curstate=state;
383 if((curstate & ThreadState.Aborted) != 0 ||
384 (curstate & ThreadState.Stopped) != 0 ||
385 (curstate & ThreadState.Unstarted) != 0) {
386 return(false);
387 } else {
388 return(true);
393 public bool IsBackground {
394 get {
395 if((state & ThreadState.Background) != 0) {
396 return(true);
397 } else {
398 return(false);
402 set {
403 if(value==true) {
404 set_state(ThreadState.Background);
405 } else {
406 clr_state(ThreadState.Background);
411 [MethodImplAttribute(MethodImplOptions.InternalCall)]
412 private extern string GetName_internal ();
414 [MethodImplAttribute(MethodImplOptions.InternalCall)]
415 private extern void SetName_internal (String name);
418 * The thread name must be shared by appdomains, so it is stored in
419 * unmanaged code.
422 public string Name {
423 get {
424 return GetName_internal ();
427 set {
428 lock (synch_lock) {
429 if(Name!=null) {
430 throw new InvalidOperationException ("Thread.Name can only be set once.");
433 SetName_internal (value);
438 [MonoTODO]
439 public ThreadPriority Priority {
440 get {
441 return(ThreadPriority.Lowest);
444 set {
448 public ThreadState ThreadState {
449 get {
450 return(state);
454 [MethodImplAttribute(MethodImplOptions.InternalCall)]
455 private extern void Abort_internal (object stateInfo);
457 public void Abort() {
458 Abort_internal (null);
461 public void Abort(object stateInfo) {
462 Abort_internal(stateInfo);
466 [MonoTODO]
467 public void Interrupt() {
470 // The current thread joins with 'this'. Set ms to 0 to block
471 // until this actually exits.
472 [MethodImplAttribute(MethodImplOptions.InternalCall)]
473 private extern bool Join_internal(int ms, IntPtr handle);
475 public void Join() {
476 if((state & ThreadState.Unstarted) != 0) {
477 throw new ThreadStateException("Thread has not been started");
480 Thread thread=CurrentThread;
482 Join_internal(Timeout.Infinite, system_thread_handle);
485 public bool Join(int millisecondsTimeout) {
486 if (millisecondsTimeout != Timeout.Infinite && millisecondsTimeout < 0)
487 throw new ArgumentException ("Timeout less than zero", "millisecondsTimeout");
489 if((state & ThreadState.Unstarted) != 0) {
490 throw new ThreadStateException("Thread has not been started");
493 Thread thread=CurrentThread;
494 return Join_internal(millisecondsTimeout, system_thread_handle);
497 public bool Join(TimeSpan timeout) {
498 // LAMESPEC: says to throw ArgumentException too
499 int ms=Convert.ToInt32(timeout.TotalMilliseconds);
501 if(ms < 0 || ms > Int32.MaxValue) {
502 throw new ArgumentOutOfRangeException("timeout out of range");
504 if((state & ThreadState.Unstarted) != 0) {
505 throw new ThreadStateException("Thread has not been started");
508 Thread thread=CurrentThread;
509 return Join_internal(ms, system_thread_handle);
512 #if NET_1_1
513 [MonoTODO ("seems required for multi-processors systems like Itanium")]
514 public static void MemoryBarrier ()
516 throw new NotImplementedException ();
518 #endif
519 [MethodImplAttribute(MethodImplOptions.InternalCall)]
520 private extern void Resume_internal();
522 #if NET_2_0
523 [Obsolete ("")]
524 #endif
525 public void Resume ()
527 if ((state & ThreadState.Unstarted) != 0 || !IsAlive ||
528 ((state & ThreadState.Suspended) == 0 && (state & ThreadState.SuspendRequested) == 0))
530 throw new ThreadStateException("Thread has not been started, or is dead");
533 Resume_internal ();
536 [MonoTODO]
537 public static void SpinWait (int iterations)
539 throw new NotImplementedException ();
542 // Launches the thread
543 [MethodImplAttribute(MethodImplOptions.InternalCall)]
544 private extern void Start_internal(IntPtr handle);
546 public void Start() {
547 lock(synch_lock) {
548 if((state & ThreadState.Unstarted) == 0) {
549 throw new ThreadStateException("Thread has already been started");
553 // Thread_internal creates the new thread, but
554 // blocks it until Start() is called later.
555 system_thread_handle=Thread_internal(threadstart);
557 if (system_thread_handle == (IntPtr) 0) {
558 throw new SystemException ("Thread creation failed");
561 // Launch this thread
562 Start_internal(system_thread_handle);
564 // Mark the thread state as Running
565 // (which is all bits
566 // cleared). Therefore just remove the
567 // Unstarted bit
568 clr_state(ThreadState.Unstarted);
572 [MethodImplAttribute(MethodImplOptions.InternalCall)]
573 private extern void Suspend_internal();
575 #if NET_2_0
576 [Obsolete ("")]
577 #endif
578 public void Suspend() {
579 if((state & ThreadState.Unstarted) != 0 || !IsAlive) {
580 throw new ThreadStateException("Thread has not been started, or is dead");
582 Suspend_internal ();
585 // Closes the system thread handle
586 [MethodImplAttribute(MethodImplOptions.InternalCall)]
587 private extern void Thread_free_internal(IntPtr handle);
589 ~Thread() {
590 // Free up the handle
591 if (system_thread_handle != (IntPtr) 0)
592 Thread_free_internal(system_thread_handle);
595 private void set_state(ThreadState set) {
596 lock(synch_lock) {
597 state |= set;
600 private void clr_state(ThreadState clr) {
601 lock(synch_lock) {
602 state &= ~clr;
606 #if NET_1_1
608 [MethodImplAttribute (MethodImplOptions.InternalCall)]
609 extern public static byte VolatileRead (ref byte address);
611 [MethodImplAttribute (MethodImplOptions.InternalCall)]
612 extern public static double VolatileRead (ref double address);
614 [MethodImplAttribute (MethodImplOptions.InternalCall)]
615 extern public static short VolatileRead (ref short address);
617 [MethodImplAttribute (MethodImplOptions.InternalCall)]
618 extern public static int VolatileRead (ref int address);
620 [MethodImplAttribute (MethodImplOptions.InternalCall)]
621 extern public static long VolatileRead (ref long address);
623 [MethodImplAttribute (MethodImplOptions.InternalCall)]
624 extern public static IntPtr VolatileRead (ref IntPtr address);
626 [MethodImplAttribute (MethodImplOptions.InternalCall)]
627 extern public static object VolatileRead (ref object address);
629 [CLSCompliant(false)]
630 [MethodImplAttribute (MethodImplOptions.InternalCall)]
631 extern public static sbyte VolatileRead (ref sbyte address);
633 [MethodImplAttribute (MethodImplOptions.InternalCall)]
634 extern public static float VolatileRead (ref float address);
636 [CLSCompliant (false)]
637 [MethodImplAttribute (MethodImplOptions.InternalCall)]
638 extern public static ushort VolatileRead (ref ushort address);
640 [CLSCompliant (false)]
641 [MethodImplAttribute (MethodImplOptions.InternalCall)]
642 extern public static uint VolatileRead (ref uint address);
644 [CLSCompliant (false)]
645 [MethodImplAttribute (MethodImplOptions.InternalCall)]
646 extern public static ulong VolatileRead (ref ulong address);
648 [CLSCompliant (false)]
649 [MethodImplAttribute (MethodImplOptions.InternalCall)]
650 extern public static UIntPtr VolatileRead (ref UIntPtr address);
652 [MethodImplAttribute (MethodImplOptions.InternalCall)]
653 extern public static void VolatileWrite (ref byte address, byte value);
655 [MethodImplAttribute (MethodImplOptions.InternalCall)]
656 extern public static void VolatileWrite (ref double address, double value);
658 [MethodImplAttribute (MethodImplOptions.InternalCall)]
659 extern public static void VolatileWrite (ref short address, short value);
661 [MethodImplAttribute (MethodImplOptions.InternalCall)]
662 extern public static void VolatileWrite (ref int address, int value);
664 [MethodImplAttribute (MethodImplOptions.InternalCall)]
665 extern public static void VolatileWrite (ref long address, long value);
667 [MethodImplAttribute (MethodImplOptions.InternalCall)]
668 extern public static void VolatileWrite (ref IntPtr address, IntPtr value);
670 [MethodImplAttribute (MethodImplOptions.InternalCall)]
671 extern public static void VolatileWrite (ref object address, object value);
673 [CLSCompliant(false)]
674 [MethodImplAttribute (MethodImplOptions.InternalCall)]
675 extern public static void VolatileWrite (ref sbyte address, sbyte value);
677 [MethodImplAttribute (MethodImplOptions.InternalCall)]
678 extern public static void VolatileWrite (ref float address, float value);
680 [CLSCompliant (false)]
681 [MethodImplAttribute (MethodImplOptions.InternalCall)]
682 extern public static void VolatileWrite (ref ushort address, ushort value);
684 [CLSCompliant (false)]
685 [MethodImplAttribute (MethodImplOptions.InternalCall)]
686 extern public static void VolatileWrite (ref uint address, uint value);
688 [CLSCompliant (false)]
689 [MethodImplAttribute (MethodImplOptions.InternalCall)]
690 extern public static void VolatileWrite (ref ulong address, ulong value);
692 [CLSCompliant (false)]
693 [MethodImplAttribute (MethodImplOptions.InternalCall)]
694 extern public static void VolatileWrite (ref UIntPtr address, UIntPtr value);
696 #endif
698 #if NET_2_0
699 [MonoTODO ("stack size is ignored")]
700 public Thread (ThreadStart start, int maxStackSize)
702 if (start == null)
703 throw new ArgumentNullException ("start");
704 if (maxStackSize < 131072)
705 throw new ArgumentException ("< 128 kb", "maxStackSize");
707 threadstart=start;
710 [MonoTODO]
711 public Thread (ParameterizedThreadStart start)
713 if (start == null)
714 throw new ArgumentNullException ("start");
716 throw new NotImplementedException ();
719 [MonoTODO]
720 public Thread (ParameterizedThreadStart start, int maxStackSize)
722 if (start == null)
723 throw new ArgumentNullException ("start");
724 if (maxStackSize < 131072)
725 throw new ArgumentException ("< 128 kb", "maxStackSize");
727 throw new NotImplementedException ();
730 [MonoTODO]
731 public ExecutionContext ExecutionContext {
732 [ReliabilityContract (Consistency.WillNotCorruptState, CER.MayFail)]
733 get { throw new NotImplementedException (); }
736 public int ManagedThreadId {
737 get { return thread_id; }
740 [MonoTODO]
741 [ReliabilityContract (Consistency.WillNotCorruptState, CER.MayFail)]
742 public static void BeginCriticalRegion ()
744 throw new NotImplementedException ();
747 [MonoTODO]
748 [ReliabilityContract (Consistency.WillNotCorruptState, CER.Success)]
749 public static void EndCriticalRegion ()
751 throw new NotImplementedException ();
754 [MonoTODO]
755 public static void BeginThreadAffinity ()
757 throw new NotImplementedException ();
760 [MonoTODO]
761 public static void EndThreadAffinity ()
763 throw new NotImplementedException ();
766 [MonoTODO]
767 public ApartmentState GetApartmentState ()
769 return this.ApartmentState;
772 [MonoTODO]
773 public void SetApartmentState (ApartmentState state)
775 this.ApartmentState = state;
778 [MonoTODO]
779 public bool TrySetApartmentState (ApartmentState state)
781 try {
782 this.ApartmentState = state;
783 return true;
785 catch (ArgumentException) {
786 throw;
788 catch {
789 return false;
793 [MonoTODO]
794 public CompressedStack GetCompressedStack ()
796 throw new NotImplementedException ();
799 [MonoTODO]
800 public void SetCompressedStack (CompressedStack stack)
802 throw new NotImplementedException ();
805 [ComVisible (false)]
806 public override int GetHashCode ()
808 // ??? overridden but not guaranteed to be unique ???
809 return thread_id;
812 [MonoTODO]
813 public void Start (object parameter)
815 throw new NotImplementedException ();
817 #endif