Merge pull request #1632 from alexanderkyte/bug24118
[mono.git] / mcs / class / corlib / System.Threading / Thread.cs
index 5e3c89e17a94fd82055a04ad9eabeceeb9e44f4a..4be83d2cd58c9807089f4146144911f26f85ccce 100644 (file)
@@ -43,7 +43,7 @@ using System.Runtime.ConstrainedExecution;
 
 namespace System.Threading {
        [StructLayout (LayoutKind.Sequential)]
-       internal class InternalThread : CriticalFinalizerObject {
+       sealed class InternalThread : CriticalFinalizerObject {
 #pragma warning disable 169, 414, 649
                #region Sync with metadata/object-internals.h
                int lock_thread_id;
@@ -137,6 +137,8 @@ namespace System.Threading {
 
                IPrincipal principal;
                int principal_version;
+               bool current_culture_set;
+               bool current_ui_culture_set;
                CultureInfo current_culture;
                CultureInfo current_ui_culture;
 
@@ -156,6 +158,9 @@ namespace System.Threading {
 
                static NamedDataSlot namedDataSlot;             
 
+               static internal CultureInfo default_culture;
+               static internal CultureInfo default_ui_culture;
+
                // can be both a ThreadStart and a ParameterizedThreadStart
                private MulticastDelegate threadstart;
                //private string thread_name=null;
@@ -401,12 +406,10 @@ namespace System.Threading {
                        ResetAbort_internal ();
                }
 
-#if NET_4_0
                [HostProtectionAttribute (SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
                public extern static bool Yield ();
-#endif
 
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
@@ -470,11 +473,13 @@ namespace System.Threading {
                public CultureInfo CurrentCulture {
                        get {
                                CultureInfo culture = current_culture;
-                               if (culture != null)
+                               if (current_culture_set && culture != null)
                                        return culture;
 
+                               if (default_culture != null)
+                                       return default_culture;
+
                                current_culture = culture = CultureInfo.ConstructCurrentCulture ();
-                               NumberFormatter.SetThreadCurrentCulture (culture);
                                return culture;
                        }
                        
@@ -485,16 +490,19 @@ namespace System.Threading {
 
                                value.CheckNeutral ();
                                current_culture = value;
-                               NumberFormatter.SetThreadCurrentCulture (value);
+                               current_culture_set = true;
                        }
                }
 
                public CultureInfo CurrentUICulture {
                        get {
                                CultureInfo culture = current_ui_culture;
-                               if (culture != null)
+                               if (current_ui_culture_set && culture != null)
                                        return culture;
 
+                               if (default_ui_culture != null)
+                                       return default_ui_culture;
+
                                current_ui_culture = culture = CultureInfo.ConstructCurrentUICulture ();
                                return culture;
                        }
@@ -503,6 +511,7 @@ namespace System.Threading {
                                if (value == null)
                                        throw new ArgumentNullException ("value");
                                current_ui_culture = value;
+                               current_ui_culture_set = true;
                        }
                }
 
@@ -576,11 +585,12 @@ namespace System.Threading {
 
                public ThreadPriority Priority {
                        get {
-                               return(ThreadPriority.Lowest);
+                               return (ThreadPriority)GetPriority (Internal);
                        }
                        
                        set {
-                               // FIXME: Implement setter.
+                               // FIXME: This doesn't do anything yet
+                               SetPriority (Internal, (int)value);
                        }
                }
 
@@ -593,6 +603,12 @@ namespace System.Threading {
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                private extern static void Abort_internal (InternalThread thread, object stateInfo);
 
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private extern static int GetPriority (InternalThread thread);
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private extern static void SetPriority (InternalThread thread, int priority);
+
                [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
                public void Abort () 
                {
@@ -672,31 +688,6 @@ namespace System.Threading {
                        }
                }
 
-#if MONOTOUCH
-               static ConstructorInfo nsautoreleasepool_ctor;
-               
-               IDisposable GetNSAutoreleasePool ()
-               {
-                       if (nsautoreleasepool_ctor == null) {
-                               Type t = Type.GetType ("MonoTouch.Foundation.NSAutoreleasePool, monotouch, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
-                               nsautoreleasepool_ctor = t.GetConstructor (Type.EmptyTypes);
-                       }
-                       return (IDisposable) nsautoreleasepool_ctor.Invoke (null);
-               }
-               
-               private void StartInternal ()
-               {
-                       using (var pool = GetNSAutoreleasePool ()) {
-                               current_thread = this;
-                       
-                               if (threadstart is ThreadStart) {
-                                       ((ThreadStart) threadstart) ();
-                               } else {
-                                       ((ParameterizedThreadStart) threadstart) (start_obj);
-                               }
-                       }
-               }
-#else
                private void StartInternal ()
                {
                        current_thread = this;
@@ -707,11 +698,10 @@ namespace System.Threading {
                                ((ParameterizedThreadStart) threadstart) (start_obj);
                        }
                }
-#endif
+
                public void Start() {
                        // propagate informations from the original thread to the new thread
-                       if (!ExecutionContext.IsFlowSuppressed ())
-                               ec_to_set = ExecutionContext.Capture ();
+                       ec_to_set = ExecutionContext.Capture (false, true);
                        Internal._serialized_principal = CurrentThread.Internal._serialized_principal;
 
                        // Thread_internal creates and starts the new thread, 
@@ -826,6 +816,8 @@ namespace System.Threading {
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
                extern public static void VolatileWrite (ref UIntPtr address, UIntPtr value);
                
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               extern static int SystemMaxStackStize ();
 
                static int CheckStackSize (int maxStackSize)
                {
@@ -840,12 +832,8 @@ namespace System.Threading {
                        if ((maxStackSize % page_size) != 0) // round up to a divisible of page size
                                maxStackSize = (maxStackSize / (page_size - 1)) * page_size;
 
-                       int default_stack_size = (IntPtr.Size / 4) * 1024 * 1024; // from wthreads.c
-
-                       if (maxStackSize > default_stack_size)
-                               return default_stack_size;
-
-                       return maxStackSize; 
+                       /* Respect the max stack size imposed by the system*/
+                       return Math.Min (maxStackSize, SystemMaxStackStize ());
                }
 
                public Thread (ThreadStart start, int maxStackSize)
@@ -874,7 +862,6 @@ namespace System.Threading {
                        Internal.stack_size = CheckStackSize (maxStackSize);
                }
 
-               [MonoTODO ("limited to CompressedStack support")]
                public ExecutionContext ExecutionContext {
                        [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
                        get {
@@ -882,6 +869,35 @@ namespace System.Threading {
                                        _ec = new ExecutionContext ();
                                return _ec;
                        }
+                       internal set {
+                               _ec = value;
+                       }
+               }
+
+               internal bool HasExecutionContext {
+                       get {
+                               return _ec != null;
+                       }
+               }
+
+               internal void BranchExecutionContext (out ExecutionContext.Switcher switcher)
+               {
+                       if (_ec == null) {
+                               switcher =  new ExecutionContext.Switcher ();
+                       } else {
+                               switcher = new ExecutionContext.Switcher (_ec);
+                               _ec.CopyOnWrite = true;
+                       }
+               }
+
+               internal void RestoreExecutionContext (ref ExecutionContext.Switcher switcher)
+               {
+                       if (switcher.IsEmpty) {
+                               _ec = null;
+                               return;
+                       }
+
+                       switcher.Restore (_ec);
                }
 
                public int ManagedThreadId {
@@ -928,14 +944,11 @@ namespace System.Threading {
 
                public bool TrySetApartmentState (ApartmentState state) 
                {
-                       /* Only throw this exception when changing the
-                        * state of another thread.  See bug 324338
-                        */
-                       if ((this != CurrentThread) &&
-                           (ThreadState & ThreadState.Unstarted) == 0)
+                       if ((ThreadState & ThreadState.Unstarted) == 0)
                                throw new ThreadStateException ("Thread was in an invalid state for the operation being executed.");
 
-                       if ((ApartmentState)Internal.apartment_state != ApartmentState.Unknown)
+                       if ((ApartmentState)Internal.apartment_state != ApartmentState.Unknown && 
+                           (ApartmentState)Internal.apartment_state != state)
                                return false;
 
                        Internal.apartment_state = (byte)state;
@@ -1011,5 +1024,10 @@ namespace System.Threading {
                        throw new NotImplementedException ();
                }
 #endif
+
+               internal CultureInfo GetCurrentUICultureNoAppX ()
+               {
+                       return CultureInfo.CurrentUICulture;
+               }
        }
 }