|
|
@@ -46,33 +46,30 @@ using System.Runtime.ConstrainedExecution;
|
|
|
|
|
|
namespace System.Threading {
|
|
|
|
|
|
- [ClassInterface (ClassInterfaceType.None)]
|
|
|
#if NET_2_0
|
|
|
- [ComVisible (true)]
|
|
|
- [ComDefaultInterface (typeof (_Thread))]
|
|
|
- public sealed class Thread : CriticalFinalizerObject, _Thread {
|
|
|
+ internal class InternalThread : CriticalFinalizerObject {
|
|
|
#else
|
|
|
- public sealed class Thread : _Thread {
|
|
|
+ internal class InternalThread {
|
|
|
#endif
|
|
|
|
|
|
#pragma warning disable 169, 414, 649
|
|
|
#region Sync with metadata/object-internals.h
|
|
|
int lock_thread_id;
|
|
|
// stores a thread handle
|
|
|
- private IntPtr system_thread_handle;
|
|
|
+ internal IntPtr system_thread_handle;
|
|
|
|
|
|
/* Note this is an opaque object (an array), not a CultureInfo */
|
|
|
private object cached_culture_info;
|
|
|
private IntPtr unused0;
|
|
|
- private bool threadpool_thread;
|
|
|
+ internal bool threadpool_thread;
|
|
|
/* accessed only from unmanaged code */
|
|
|
private IntPtr name;
|
|
|
private int name_len;
|
|
|
- private ThreadState state = ThreadState.Unstarted;
|
|
|
+ private ThreadState state;
|
|
|
private object abort_exc;
|
|
|
private int abort_state_handle;
|
|
|
/* thread_id is only accessed from unmanaged code */
|
|
|
- private Int64 thread_id;
|
|
|
+ internal Int64 thread_id;
|
|
|
|
|
|
/* start_notify is used by the runtime to signal that Start()
|
|
|
* is ok to return
|
|
|
@@ -83,8 +80,7 @@ namespace System.Threading {
|
|
|
private IntPtr jit_data;
|
|
|
private IntPtr lock_data;
|
|
|
Context current_appcontext;
|
|
|
- int stack_size;
|
|
|
- object start_obj;
|
|
|
+ internal int stack_size;
|
|
|
private IntPtr appdomain_refs;
|
|
|
private int interruption_requested;
|
|
|
private IntPtr suspend_event;
|
|
|
@@ -98,12 +94,8 @@ namespace System.Threading {
|
|
|
private bool thread_dump_requested;
|
|
|
private IntPtr end_stack;
|
|
|
private bool thread_interrupt_requested;
|
|
|
-#if NET_2_1
|
|
|
- private byte apartment_state;
|
|
|
-#else
|
|
|
- private byte apartment_state = (byte)ApartmentState.Unknown;
|
|
|
-#endif
|
|
|
- volatile int critical_region_level;
|
|
|
+ internal byte apartment_state;
|
|
|
+ internal volatile int critical_region_level;
|
|
|
private int small_id;
|
|
|
private IntPtr manage_callback;
|
|
|
private object pending_exception;
|
|
|
@@ -124,10 +116,55 @@ namespace System.Threading {
|
|
|
#endregion
|
|
|
#pragma warning restore 169, 414, 649
|
|
|
|
|
|
- // the name of local_slots is important as it's used by the runtime.
|
|
|
- [ThreadStatic]
|
|
|
+#if NET_2_0
|
|
|
+ internal int managed_id;
|
|
|
+#endif
|
|
|
+
|
|
|
+ internal IPrincipal _principal;
|
|
|
+
|
|
|
+ /* If the current_lcid() isn't known by CultureInfo,
|
|
|
+ * it will throw an exception which may cause
|
|
|
+ * String.Concat to try and recursively look up the
|
|
|
+ * CurrentCulture, which will throw an exception, etc.
|
|
|
+ * Use a boolean to short-circuit this scenario.
|
|
|
+ */
|
|
|
+ internal bool in_currentculture=false;
|
|
|
+
|
|
|
+ // Closes the system thread handle
|
|
|
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
|
|
|
+ private extern void Thread_free_internal(IntPtr handle);
|
|
|
+
|
|
|
+#if NET_2_0
|
|
|
+ [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
|
|
|
+#endif
|
|
|
+ ~InternalThread() {
|
|
|
+ Thread_free_internal(system_thread_handle);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ [ClassInterface (ClassInterfaceType.None)]
|
|
|
+#if NET_2_0
|
|
|
+ [ComVisible (true)]
|
|
|
+ [ComDefaultInterface (typeof (_Thread))]
|
|
|
+ public sealed class Thread : CriticalFinalizerObject, _Thread {
|
|
|
+#else
|
|
|
+ public sealed class Thread : _Thread {
|
|
|
+#endif
|
|
|
+
|
|
|
+ #region Sync with metadata/object-internals.h
|
|
|
+ private InternalThread internal_thread;
|
|
|
+ object start_obj;
|
|
|
+ private ExecutionContext ec_to_set;
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ // the name of local_slots, current_thread and _ec is
|
|
|
+ // important because they are used by the runtime.
|
|
|
+ [ThreadStatic]
|
|
|
static object[] local_slots;
|
|
|
|
|
|
+ [ThreadStatic]
|
|
|
+ static Thread current_thread;
|
|
|
+
|
|
|
/* The actual ExecutionContext of the thread. It's
|
|
|
ThreadStatic so that it's not shared between
|
|
|
AppDomains. */
|
|
|
@@ -138,12 +175,20 @@ namespace System.Threading {
|
|
|
private MulticastDelegate threadstart;
|
|
|
//private string thread_name=null;
|
|
|
|
|
|
-#if NET_2_0
|
|
|
+#if NET_2_0
|
|
|
private static int _managed_id_counter;
|
|
|
- private int managed_id;
|
|
|
-#endif
|
|
|
-
|
|
|
- private IPrincipal _principal;
|
|
|
+#endif
|
|
|
+
|
|
|
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
|
|
|
+ private extern void ConstructInternalThread ();
|
|
|
+
|
|
|
+ private InternalThread Internal {
|
|
|
+ get {
|
|
|
+ if (internal_thread == null)
|
|
|
+ ConstructInternalThread ();
|
|
|
+ return internal_thread;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
public static Context CurrentContext {
|
|
|
[SecurityPermission (SecurityAction.LinkDemand, Infrastructure=true)]
|
|
|
@@ -156,7 +201,7 @@ namespace System.Threading {
|
|
|
public static IPrincipal CurrentPrincipal {
|
|
|
get {
|
|
|
IPrincipal p = null;
|
|
|
- Thread th = CurrentThread;
|
|
|
+ InternalThread th = CurrentThread.Internal;
|
|
|
lock (th) {
|
|
|
p = th._principal;
|
|
|
if (p == null) {
|
|
|
@@ -168,27 +213,29 @@ namespace System.Threading {
|
|
|
}
|
|
|
[SecurityPermission (SecurityAction.Demand, ControlPrincipal = true)]
|
|
|
set {
|
|
|
- CurrentThread._principal = value;
|
|
|
+ CurrentThread.Internal._principal = value;
|
|
|
}
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
// Looks up the object associated with the current thread
|
|
|
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
|
|
- private extern static Thread CurrentThread_internal();
|
|
|
-
|
|
|
+ private extern static InternalThread CurrentInternalThread_internal();
|
|
|
+
|
|
|
public static Thread CurrentThread {
|
|
|
#if NET_2_0
|
|
|
[ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
|
|
|
#endif
|
|
|
get {
|
|
|
- return(CurrentThread_internal());
|
|
|
+ if (current_thread == null)
|
|
|
+ current_thread = new Thread (CurrentInternalThread_internal ());
|
|
|
+ return current_thread;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
internal static int CurrentThreadId {
|
|
|
get {
|
|
|
- return (int)(CurrentThread.thread_id);
|
|
|
+ return (int)(CurrentThread.internal_thread.thread_id);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -322,16 +369,15 @@ namespace System.Threading {
|
|
|
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
|
|
private extern IntPtr Thread_internal (MulticastDelegate start);
|
|
|
|
|
|
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
|
|
|
- private extern void Thread_init ();
|
|
|
-
|
|
|
public Thread(ThreadStart start) {
|
|
|
if(start==null) {
|
|
|
throw new ArgumentNullException("Null ThreadStart");
|
|
|
}
|
|
|
threadstart=start;
|
|
|
+ }
|
|
|
|
|
|
- Thread_init ();
|
|
|
+ private Thread (InternalThread it) {
|
|
|
+ internal_thread = it;
|
|
|
}
|
|
|
|
|
|
#if !NET_2_1
|
|
|
@@ -343,7 +389,7 @@ namespace System.Threading {
|
|
|
if ((ThreadState & ThreadState.Stopped) != 0)
|
|
|
throw new ThreadStateException ("Thread is dead; state can not be accessed.");
|
|
|
|
|
|
- return (ApartmentState)apartment_state;
|
|
|
+ return (ApartmentState)Internal.apartment_state;
|
|
|
}
|
|
|
|
|
|
set {
|
|
|
@@ -361,8 +407,8 @@ namespace System.Threading {
|
|
|
if (value != ApartmentState.STA && value != ApartmentState.MTA)
|
|
|
throw new ArgumentOutOfRangeException ("value is not a valid apartment state.");
|
|
|
|
|
|
- if ((ApartmentState)apartment_state == ApartmentState.Unknown)
|
|
|
- apartment_state = (byte)value;
|
|
|
+ if ((ApartmentState)Internal.apartment_state == ApartmentState.Unknown)
|
|
|
+ Internal.apartment_state = (byte)value;
|
|
|
#endif
|
|
|
}
|
|
|
}
|
|
|
@@ -372,37 +418,32 @@ namespace System.Threading {
|
|
|
//private static extern int current_lcid ();
|
|
|
|
|
|
[MethodImplAttribute (MethodImplOptions.InternalCall)]
|
|
|
- private extern CultureInfo GetCachedCurrentCulture ();
|
|
|
+ private extern static CultureInfo GetCachedCurrentCulture (InternalThread thread);
|
|
|
|
|
|
[MethodImplAttribute (MethodImplOptions.InternalCall)]
|
|
|
- private extern byte[] GetSerializedCurrentCulture ();
|
|
|
+ private extern static byte[] GetSerializedCurrentCulture (InternalThread thread);
|
|
|
|
|
|
[MethodImplAttribute (MethodImplOptions.InternalCall)]
|
|
|
private extern void SetCachedCurrentCulture (CultureInfo culture);
|
|
|
|
|
|
[MethodImplAttribute (MethodImplOptions.InternalCall)]
|
|
|
- private extern void SetSerializedCurrentCulture (byte[] culture);
|
|
|
+ private extern static void SetSerializedCurrentCulture (InternalThread thread, byte[] culture);
|
|
|
|
|
|
[MethodImplAttribute (MethodImplOptions.InternalCall)]
|
|
|
- private extern CultureInfo GetCachedCurrentUICulture ();
|
|
|
+ private extern static CultureInfo GetCachedCurrentUICulture (InternalThread thread);
|
|
|
|
|
|
[MethodImplAttribute (MethodImplOptions.InternalCall)]
|
|
|
- private extern byte[] GetSerializedCurrentUICulture ();
|
|
|
+ private extern static byte[] GetSerializedCurrentUICulture (InternalThread thread);
|
|
|
|
|
|
[MethodImplAttribute (MethodImplOptions.InternalCall)]
|
|
|
private extern void SetCachedCurrentUICulture (CultureInfo culture);
|
|
|
|
|
|
[MethodImplAttribute (MethodImplOptions.InternalCall)]
|
|
|
- private extern void SetSerializedCurrentUICulture (byte[] culture);
|
|
|
-
|
|
|
- /* If the current_lcid() isn't known by CultureInfo,
|
|
|
- * it will throw an exception which may cause
|
|
|
- * String.Concat to try and recursively look up the
|
|
|
- * CurrentCulture, which will throw an exception, etc.
|
|
|
- * Use a boolean to short-circuit this scenario.
|
|
|
- */
|
|
|
- private bool in_currentculture=false;
|
|
|
+ private extern static void SetSerializedCurrentUICulture (InternalThread thread, byte[] culture);
|
|
|
|
|
|
+ /* FIXME: in_currentculture exists once, but
|
|
|
+ culture_lock is once per appdomain. Is it correct
|
|
|
+ to lock this way? */
|
|
|
static object culture_lock = new object ();
|
|
|
|
|
|
/*
|
|
|
@@ -416,18 +457,18 @@ namespace System.Threading {
|
|
|
*/
|
|
|
public CultureInfo CurrentCulture {
|
|
|
get {
|
|
|
- if (in_currentculture)
|
|
|
+ if (Internal.in_currentculture)
|
|
|
/* Bail out */
|
|
|
return CultureInfo.InvariantCulture;
|
|
|
|
|
|
- CultureInfo culture = GetCachedCurrentCulture ();
|
|
|
+ CultureInfo culture = GetCachedCurrentCulture (Internal);
|
|
|
if (culture != null)
|
|
|
return culture;
|
|
|
|
|
|
- byte[] arr = GetSerializedCurrentCulture ();
|
|
|
+ byte[] arr = GetSerializedCurrentCulture (Internal);
|
|
|
if (arr == null) {
|
|
|
lock (culture_lock) {
|
|
|
- in_currentculture=true;
|
|
|
+ Internal.in_currentculture=true;
|
|
|
culture = CultureInfo.ConstructCurrentCulture ();
|
|
|
//
|
|
|
// Don't serialize the culture in this case to avoid
|
|
|
@@ -435,7 +476,7 @@ namespace System.Threading {
|
|
|
// common case when the culture is not set explicitly.
|
|
|
//
|
|
|
SetCachedCurrentCulture (culture);
|
|
|
- in_currentculture = false;
|
|
|
+ Internal.in_currentculture = false;
|
|
|
NumberFormatter.SetThreadCurrentCulture (culture);
|
|
|
return culture;
|
|
|
}
|
|
|
@@ -445,14 +486,14 @@ namespace System.Threading {
|
|
|
* No cultureinfo object exists for this domain, so create one
|
|
|
* by deserializing the serialized form.
|
|
|
*/
|
|
|
- in_currentculture = true;
|
|
|
+ Internal.in_currentculture = true;
|
|
|
try {
|
|
|
BinaryFormatter bf = new BinaryFormatter ();
|
|
|
MemoryStream ms = new MemoryStream (arr);
|
|
|
culture = (CultureInfo)bf.Deserialize (ms);
|
|
|
SetCachedCurrentCulture (culture);
|
|
|
} finally {
|
|
|
- in_currentculture = false;
|
|
|
+ Internal.in_currentculture = false;
|
|
|
}
|
|
|
|
|
|
NumberFormatter.SetThreadCurrentCulture (culture);
|
|
|
@@ -464,12 +505,12 @@ namespace System.Threading {
|
|
|
if (value == null)
|
|
|
throw new ArgumentNullException ("value");
|
|
|
|
|
|
- CultureInfo culture = GetCachedCurrentCulture ();
|
|
|
+ CultureInfo culture = GetCachedCurrentCulture (Internal);
|
|
|
if (culture == value)
|
|
|
return;
|
|
|
|
|
|
value.CheckNeutral ();
|
|
|
- in_currentculture = true;
|
|
|
+ Internal.in_currentculture = true;
|
|
|
try {
|
|
|
SetCachedCurrentCulture (value);
|
|
|
|
|
|
@@ -487,9 +528,9 @@ namespace System.Threading {
|
|
|
value.cached_serialized_form = serialized_form;
|
|
|
}
|
|
|
|
|
|
- SetSerializedCurrentCulture (serialized_form);
|
|
|
+ SetSerializedCurrentCulture (Internal, serialized_form);
|
|
|
} finally {
|
|
|
- in_currentculture = false;
|
|
|
+ Internal.in_currentculture = false;
|
|
|
}
|
|
|
NumberFormatter.SetThreadCurrentCulture (value);
|
|
|
}
|
|
|
@@ -497,18 +538,18 @@ namespace System.Threading {
|
|
|
|
|
|
public CultureInfo CurrentUICulture {
|
|
|
get {
|
|
|
- if (in_currentculture)
|
|
|
+ if (Internal.in_currentculture)
|
|
|
/* Bail out */
|
|
|
return CultureInfo.InvariantCulture;
|
|
|
|
|
|
- CultureInfo culture = GetCachedCurrentUICulture ();
|
|
|
+ CultureInfo culture = GetCachedCurrentUICulture (Internal);
|
|
|
if (culture != null)
|
|
|
return culture;
|
|
|
|
|
|
- byte[] arr = GetSerializedCurrentUICulture ();
|
|
|
+ byte[] arr = GetSerializedCurrentUICulture (Internal);
|
|
|
if (arr == null) {
|
|
|
lock (culture_lock) {
|
|
|
- in_currentculture=true;
|
|
|
+ Internal.in_currentculture=true;
|
|
|
/* We don't
|
|
|
* distinguish
|
|
|
* between
|
|
|
@@ -522,7 +563,7 @@ namespace System.Threading {
|
|
|
// common case when the culture is not set explicitly.
|
|
|
//
|
|
|
SetCachedCurrentUICulture (culture);
|
|
|
- in_currentculture = false;
|
|
|
+ Internal.in_currentculture = false;
|
|
|
return culture;
|
|
|
}
|
|
|
}
|
|
|
@@ -531,7 +572,7 @@ namespace System.Threading {
|
|
|
* No cultureinfo object exists for this domain, so create one
|
|
|
* by deserializing the serialized form.
|
|
|
*/
|
|
|
- in_currentculture = true;
|
|
|
+ Internal.in_currentculture = true;
|
|
|
try {
|
|
|
BinaryFormatter bf = new BinaryFormatter ();
|
|
|
MemoryStream ms = new MemoryStream (arr);
|
|
|
@@ -539,19 +580,19 @@ namespace System.Threading {
|
|
|
SetCachedCurrentUICulture (culture);
|
|
|
}
|
|
|
finally {
|
|
|
- in_currentculture = false;
|
|
|
+ Internal.in_currentculture = false;
|
|
|
}
|
|
|
|
|
|
return culture;
|
|
|
}
|
|
|
|
|
|
set {
|
|
|
- in_currentculture = true;
|
|
|
-
|
|
|
+ Internal.in_currentculture = true;
|
|
|
+
|
|
|
if (value == null)
|
|
|
throw new ArgumentNullException ("value");
|
|
|
|
|
|
- CultureInfo culture = GetCachedCurrentUICulture ();
|
|
|
+ CultureInfo culture = GetCachedCurrentUICulture (Internal);
|
|
|
if (culture == value)
|
|
|
return;
|
|
|
|
|
|
@@ -572,9 +613,9 @@ namespace System.Threading {
|
|
|
value.cached_serialized_form = serialized_form;
|
|
|
}
|
|
|
|
|
|
- SetSerializedCurrentUICulture (serialized_form);
|
|
|
+ SetSerializedCurrentUICulture (Internal, serialized_form);
|
|
|
} finally {
|
|
|
- in_currentculture = false;
|
|
|
+ Internal.in_currentculture = false;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -587,16 +628,16 @@ namespace System.Threading {
|
|
|
|
|
|
internal bool IsThreadPoolThreadInternal {
|
|
|
get {
|
|
|
- return threadpool_thread;
|
|
|
+ return Internal.threadpool_thread;
|
|
|
}
|
|
|
set {
|
|
|
- threadpool_thread = value;
|
|
|
+ Internal.threadpool_thread = value;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public bool IsAlive {
|
|
|
get {
|
|
|
- ThreadState curstate = GetState ();
|
|
|
+ ThreadState curstate = GetState (Internal);
|
|
|
|
|
|
if((curstate & ThreadState.Aborted) != 0 ||
|
|
|
(curstate & ThreadState.Stopped) != 0 ||
|
|
|
@@ -610,7 +651,7 @@ namespace System.Threading {
|
|
|
|
|
|
public bool IsBackground {
|
|
|
get {
|
|
|
- ThreadState thread_state = GetState ();
|
|
|
+ ThreadState thread_state = GetState (Internal);
|
|
|
if ((thread_state & ThreadState.Stopped) != 0)
|
|
|
throw new ThreadStateException ("Thread is dead; state can not be accessed.");
|
|
|
|
|
|
@@ -619,18 +660,18 @@ namespace System.Threading {
|
|
|
|
|
|
set {
|
|
|
if (value) {
|
|
|
- SetState (ThreadState.Background);
|
|
|
+ SetState (Internal, ThreadState.Background);
|
|
|
} else {
|
|
|
- ClrState (ThreadState.Background);
|
|
|
+ ClrState (Internal, ThreadState.Background);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
|
|
- private extern string GetName_internal ();
|
|
|
+ private extern static string GetName_internal (InternalThread thread);
|
|
|
|
|
|
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
|
|
- private extern void SetName_internal (String name);
|
|
|
+ private extern static void SetName_internal (InternalThread thread, String name);
|
|
|
|
|
|
/*
|
|
|
* The thread name must be shared by appdomains, so it is stored in
|
|
|
@@ -639,11 +680,11 @@ namespace System.Threading {
|
|
|
|
|
|
public string Name {
|
|
|
get {
|
|
|
- return GetName_internal ();
|
|
|
+ return GetName_internal (Internal);
|
|
|
}
|
|
|
|
|
|
set {
|
|
|
- SetName_internal (value);
|
|
|
+ SetName_internal (Internal, value);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -661,47 +702,47 @@ namespace System.Threading {
|
|
|
|
|
|
public ThreadState ThreadState {
|
|
|
get {
|
|
|
- return GetState ();
|
|
|
+ return GetState (Internal);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
|
|
- private extern void Abort_internal (object stateInfo);
|
|
|
+ private extern static void Abort_internal (InternalThread thread, object stateInfo);
|
|
|
|
|
|
[SecurityPermission (SecurityAction.Demand, ControlThread=true)]
|
|
|
public void Abort ()
|
|
|
{
|
|
|
- Abort_internal (null);
|
|
|
+ Abort_internal (Internal, null);
|
|
|
}
|
|
|
|
|
|
#if !NET_2_1
|
|
|
[SecurityPermission (SecurityAction.Demand, ControlThread=true)]
|
|
|
public void Abort (object stateInfo)
|
|
|
{
|
|
|
- Abort_internal (stateInfo);
|
|
|
+ Abort_internal (Internal, stateInfo);
|
|
|
}
|
|
|
|
|
|
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
|
|
internal extern object GetAbortExceptionState ();
|
|
|
|
|
|
[MethodImplAttribute (MethodImplOptions.InternalCall)]
|
|
|
- private extern void Interrupt_internal ();
|
|
|
+ private extern static void Interrupt_internal (InternalThread thread);
|
|
|
|
|
|
[SecurityPermission (SecurityAction.Demand, ControlThread=true)]
|
|
|
public void Interrupt ()
|
|
|
{
|
|
|
- Interrupt_internal ();
|
|
|
+ Interrupt_internal (Internal);
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
// The current thread joins with 'this'. Set ms to 0 to block
|
|
|
// until this actually exits.
|
|
|
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
|
|
- private extern bool Join_internal(int ms, IntPtr handle);
|
|
|
+ private extern static bool Join_internal(InternalThread thread, int ms, IntPtr handle);
|
|
|
|
|
|
public void Join()
|
|
|
{
|
|
|
- Join_internal(Timeout.Infinite, system_thread_handle);
|
|
|
+ Join_internal(Internal, Timeout.Infinite, Internal.system_thread_handle);
|
|
|
}
|
|
|
|
|
|
public bool Join(int millisecondsTimeout)
|
|
|
@@ -709,7 +750,7 @@ namespace System.Threading {
|
|
|
if (millisecondsTimeout != Timeout.Infinite && millisecondsTimeout < 0)
|
|
|
throw new ArgumentException ("Timeout less than zero", "millisecondsTimeout");
|
|
|
|
|
|
- return Join_internal(millisecondsTimeout, system_thread_handle);
|
|
|
+ return Join_internal(Internal, millisecondsTimeout, Internal.system_thread_handle);
|
|
|
}
|
|
|
|
|
|
#if !NET_2_1
|
|
|
@@ -721,7 +762,7 @@ namespace System.Threading {
|
|
|
if(ms < 0 || ms > Int32.MaxValue) {
|
|
|
throw new ArgumentOutOfRangeException("timeout out of range");
|
|
|
}
|
|
|
- return Join_internal(ms, system_thread_handle);
|
|
|
+ return Join_internal(Internal, ms, Internal.system_thread_handle);
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
@@ -764,6 +805,8 @@ namespace System.Threading {
|
|
|
#if NET_2_1 && !MONOTOUCH
|
|
|
private void StartSafe ()
|
|
|
{
|
|
|
+ current_thread = this;
|
|
|
+
|
|
|
try {
|
|
|
if (threadstart is ThreadStart) {
|
|
|
((ThreadStart) threadstart) ();
|
|
|
@@ -797,6 +840,21 @@ namespace System.Threading {
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
+ private void StartUnsafe ()
|
|
|
+ {
|
|
|
+ current_thread = this;
|
|
|
+
|
|
|
+#if NET_2_0
|
|
|
+ if (threadstart is ThreadStart) {
|
|
|
+ ((ThreadStart) threadstart) ();
|
|
|
+ } else {
|
|
|
+ ((ParameterizedThreadStart) threadstart) (start_obj);
|
|
|
+ }
|
|
|
+#else
|
|
|
+ ((ThreadStart) threadstart) ();
|
|
|
+#endif
|
|
|
+ }
|
|
|
+
|
|
|
public void Start() {
|
|
|
// propagate informations from the original thread to the new thread
|
|
|
#if NET_2_0
|
|
|
@@ -808,21 +866,21 @@ namespace System.Threading {
|
|
|
if (SecurityManager.SecurityEnabled)
|
|
|
ec_to_set = ExecutionContext.Capture ();
|
|
|
#endif
|
|
|
- if (CurrentThread._principal != null)
|
|
|
- _principal = CurrentThread._principal;
|
|
|
+ if (CurrentThread.Internal._principal != null)
|
|
|
+ Internal._principal = CurrentThread.Internal._principal;
|
|
|
|
|
|
// Thread_internal creates and starts the new thread,
|
|
|
#if NET_2_1 && !MONOTOUCH
|
|
|
if (Thread_internal((ThreadStart) StartSafe) == (IntPtr) 0)
|
|
|
#else
|
|
|
- if (Thread_internal(threadstart) == (IntPtr) 0)
|
|
|
+ if (Thread_internal((ThreadStart) StartUnsafe) == (IntPtr) 0)
|
|
|
#endif
|
|
|
throw new SystemException ("Thread creation failed.");
|
|
|
}
|
|
|
|
|
|
#if !NET_2_1
|
|
|
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
|
|
- private extern void Suspend_internal();
|
|
|
+ private extern static void Suspend_internal(InternalThread thread);
|
|
|
|
|
|
#if NET_2_0
|
|
|
[Obsolete ("")]
|
|
|
@@ -830,29 +888,18 @@ namespace System.Threading {
|
|
|
[SecurityPermission (SecurityAction.Demand, ControlThread=true)]
|
|
|
public void Suspend ()
|
|
|
{
|
|
|
- Suspend_internal ();
|
|
|
+ Suspend_internal (Internal);
|
|
|
}
|
|
|
#endif // !NET_2_1
|
|
|
|
|
|
- // Closes the system thread handle
|
|
|
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
|
|
|
- private extern void Thread_free_internal(IntPtr handle);
|
|
|
-
|
|
|
-#if NET_2_0
|
|
|
- [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
|
|
|
-#endif
|
|
|
- ~Thread() {
|
|
|
- Thread_free_internal(system_thread_handle);
|
|
|
- }
|
|
|
-
|
|
|
[MethodImplAttribute (MethodImplOptions.InternalCall)]
|
|
|
- extern private void SetState (ThreadState set);
|
|
|
-
|
|
|
+ extern private static void SetState (InternalThread thread, ThreadState set);
|
|
|
+
|
|
|
[MethodImplAttribute (MethodImplOptions.InternalCall)]
|
|
|
- extern private void ClrState (ThreadState clr);
|
|
|
-
|
|
|
+ extern private static void ClrState (InternalThread thread, ThreadState clr);
|
|
|
+
|
|
|
[MethodImplAttribute (MethodImplOptions.InternalCall)]
|
|
|
- extern private ThreadState GetState ();
|
|
|
+ extern private static ThreadState GetState (InternalThread thread);
|
|
|
|
|
|
#if NET_1_1
|
|
|
|
|
|
@@ -959,8 +1006,7 @@ namespace System.Threading {
|
|
|
throw new ArgumentException ("< 128 kb", "maxStackSize");
|
|
|
|
|
|
threadstart = start;
|
|
|
- stack_size = maxStackSize;
|
|
|
- Thread_init ();
|
|
|
+ Internal.stack_size = maxStackSize;
|
|
|
}
|
|
|
|
|
|
public Thread (ParameterizedThreadStart start)
|
|
|
@@ -969,7 +1015,6 @@ namespace System.Threading {
|
|
|
throw new ArgumentNullException ("start");
|
|
|
|
|
|
threadstart = start;
|
|
|
- Thread_init ();
|
|
|
}
|
|
|
|
|
|
public Thread (ParameterizedThreadStart start, int maxStackSize)
|
|
|
@@ -980,8 +1025,7 @@ namespace System.Threading {
|
|
|
throw new ArgumentException ("< 128 kb", "maxStackSize");
|
|
|
|
|
|
threadstart = start;
|
|
|
- stack_size = maxStackSize;
|
|
|
- Thread_init ();
|
|
|
+ Internal.stack_size = maxStackSize;
|
|
|
}
|
|
|
|
|
|
[MonoTODO ("limited to CompressedStack support")]
|
|
|
@@ -997,26 +1041,26 @@ namespace System.Threading {
|
|
|
public int ManagedThreadId {
|
|
|
[ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
|
|
|
get {
|
|
|
- if (managed_id == 0) {
|
|
|
+ if (Internal.managed_id == 0) {
|
|
|
int new_managed_id = GetNewManagedId ();
|
|
|
|
|
|
- Interlocked.CompareExchange (ref managed_id, new_managed_id, 0);
|
|
|
+ Interlocked.CompareExchange (ref Internal.managed_id, new_managed_id, 0);
|
|
|
}
|
|
|
|
|
|
- return managed_id;
|
|
|
+ return Internal.managed_id;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
[ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
|
|
|
public static void BeginCriticalRegion ()
|
|
|
{
|
|
|
- CurrentThread.critical_region_level++;
|
|
|
+ CurrentThread.Internal.critical_region_level++;
|
|
|
}
|
|
|
|
|
|
[ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
|
|
|
public static void EndCriticalRegion ()
|
|
|
{
|
|
|
- CurrentThread.critical_region_level--;
|
|
|
+ CurrentThread.Internal.critical_region_level--;
|
|
|
}
|
|
|
|
|
|
[ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
|
|
|
@@ -1034,7 +1078,7 @@ namespace System.Threading {
|
|
|
#if !NET_2_1
|
|
|
public ApartmentState GetApartmentState ()
|
|
|
{
|
|
|
- return (ApartmentState)apartment_state;
|
|
|
+ return (ApartmentState)Internal.apartment_state;
|
|
|
}
|
|
|
|
|
|
public void SetApartmentState (ApartmentState state)
|
|
|
@@ -1052,10 +1096,10 @@ namespace System.Threading {
|
|
|
(ThreadState & ThreadState.Unstarted) == 0)
|
|
|
throw new ThreadStateException ("Thread was in an invalid state for the operation being executed.");
|
|
|
|
|
|
- if ((ApartmentState)apartment_state != ApartmentState.Unknown)
|
|
|
+ if ((ApartmentState)Internal.apartment_state != ApartmentState.Unknown)
|
|
|
return false;
|
|
|
|
|
|
- apartment_state = (byte)state;
|
|
|
+ Internal.apartment_state = (byte)state;
|
|
|
|
|
|
return true;
|
|
|
}
|