[corlib] Flow CultureInfo from parent thread. Fixes #43193
authorMarek Safar <marek.safar@gmail.com>
Tue, 30 Aug 2016 15:00:35 +0000 (17:00 +0200)
committerMarek Safar <marek.safar@gmail.com>
Tue, 30 Aug 2016 18:42:25 +0000 (20:42 +0200)
mcs/class/corlib/ReferenceSources/AppContextSwitches.cs
mcs/class/corlib/System.Globalization/CultureInfo.cs
mcs/class/corlib/System.Threading/Thread.cs
mcs/class/corlib/Test/System.Globalization/CultureInfoTest.cs
mcs/class/referencesource/mscorlib/system/threading/thread.cs

index 55d45d833e3f6a5c74d371e8e118d0e5861f7edd..8874423d8492c49421debe9a2795fd721964f6a8 100644 (file)
@@ -2,5 +2,6 @@ namespace System {
        static class AppContextSwitches {
                public static readonly bool ThrowExceptionIfDisposedCancellationTokenSource = true;
                public static readonly bool SetActorAsReferenceWhenCopyingClaimsIdentity = false;
+               public static readonly bool NoAsyncCurrentCulture = false;
        }
 }
\ No newline at end of file
index 66914166bc3d20efc61cc573ff314535515711b2..e6741d4d3caf2c0cf6467e382e9821c4281646eb 100644 (file)
@@ -116,6 +116,9 @@ namespace System.Globalization
                const int CalendarTypeBits = 8;
 
                const string MSG_READONLY = "This instance is read only";
+
+               static volatile CultureInfo s_DefaultThreadCurrentUICulture;
+               static volatile CultureInfo s_DefaultThreadCurrentCulture;
                
                public static CultureInfo InvariantCulture {
                        get {
@@ -128,7 +131,7 @@ namespace System.Globalization
                                return Thread.CurrentThread.CurrentCulture;
                        }
                        set {
-                               throw new NotImplementedException ();
+                               Thread.CurrentThread.CurrentCulture = value;
                        }
                }
 
@@ -137,7 +140,7 @@ namespace System.Globalization
                                return Thread.CurrentThread.CurrentUICulture;
                        }
                        set {
-                               throw new NotImplementedException ();
+                               Thread.CurrentThread.CurrentUICulture = value;
                        }
                }
 
@@ -511,7 +514,7 @@ namespace System.Globalization
                        }
                }
 
-               internal void CheckNeutral ()
+               void CheckNeutral ()
                {
                }
 
@@ -1070,19 +1073,19 @@ namespace System.Globalization
                
                public static CultureInfo DefaultThreadCurrentCulture {
                        get {
-                               return Thread.default_culture;
+                               return s_DefaultThreadCurrentCulture;
                        }
                        set {
-                               Thread.default_culture = value;
+                               s_DefaultThreadCurrentCulture = value;
                        }
                }
                
                public static CultureInfo DefaultThreadCurrentUICulture {
                        get {
-                               return Thread.default_ui_culture;
+                               return s_DefaultThreadCurrentUICulture;
                        }
                        set {
-                               Thread.default_ui_culture = value;
+                               s_DefaultThreadCurrentUICulture = value;
                        }
                }
 
@@ -1092,6 +1095,19 @@ namespace System.Globalization
                        }
                }
 
+               internal static CultureInfo UserDefaultUICulture {
+                       get {
+                               return ConstructCurrentUICulture ();
+                       }
+               }
+
+               internal static CultureInfo UserDefaultCulture {
+                       get {
+                               return ConstructCurrentCulture ();
+                       }
+               }
+
+
 #region reference sources
                // TODO:
                internal static readonly bool IsTaiwanSku;
@@ -1144,6 +1160,19 @@ namespace System.Globalization
             return true;
         }
 
+        internal static bool VerifyCultureName(CultureInfo culture, bool throwException) {
+            Contract.Assert(culture!=null, "[CultureInfo.VerifyCultureName]culture!=null");
+
+            //If we have an instance of one of our CultureInfos, the user can't have changed the
+            //name and we know that all names are valid in files.
+            if (!culture.m_isInherited) {
+                return true;
+            }
+
+            return VerifyCultureName(culture.Name, throwException);
+
+        }
+
 #endregion
        }
 }
index 7527667be3f9394a2a95fc7a949e38b774fac6ef..f1924b22e07ef7e603d8d2446de8ff0a85ff1e7a 100644 (file)
@@ -122,10 +122,6 @@ namespace System.Threading {
 
                IPrincipal principal;
                int principal_version;
-               bool current_culture_set;
-               bool current_ui_culture_set;
-               CultureInfo current_culture;
-               CultureInfo current_ui_culture;
 
                // the name of current_thread is
                // important because they are used by the runtime.
@@ -133,9 +129,6 @@ namespace System.Threading {
                [ThreadStatic]
                static Thread current_thread;
 
-               static internal CultureInfo default_culture;
-               static internal CultureInfo default_ui_culture;
-
                // can be both a ThreadStart and a ParameterizedThreadStart
                private MulticastDelegate m_Delegate;
 
@@ -340,54 +333,6 @@ namespace System.Threading {
                        }
                }
 
-               //[MethodImplAttribute (MethodImplOptions.InternalCall)]
-               //private static extern int current_lcid ();
-
-               public CultureInfo CurrentCulture {
-                       get {
-                               CultureInfo culture = current_culture;
-                               if (current_culture_set && culture != null)
-                                       return culture;
-
-                               if (default_culture != null)
-                                       return default_culture;
-
-                               current_culture = culture = CultureInfo.ConstructCurrentCulture ();
-                               return culture;
-                       }
-                       
-                       [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
-                       set {
-                               if (value == null)
-                                       throw new ArgumentNullException ("value");
-
-                               value.CheckNeutral ();
-                               current_culture = value;
-                               current_culture_set = true;
-                       }
-               }
-
-               public CultureInfo CurrentUICulture {
-                       get {
-                               CultureInfo culture = current_ui_culture;
-                               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;
-                       }
-                       
-                       set {
-                               if (value == null)
-                                       throw new ArgumentNullException ("value");
-                               current_ui_culture = value;
-                               current_ui_culture_set = true;
-                       }
-               }
-
                public bool IsThreadPoolThread {
                        get {
                                return IsThreadPoolThreadInternal;
@@ -723,11 +668,6 @@ namespace System.Threading {
                        return ManagedThreadId;
                }
 
-               internal CultureInfo GetCurrentUICultureNoAppX ()
-               {
-                       return CultureInfo.CurrentUICulture;
-               }
-
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                internal static extern void GetStackTraces (out Thread[] threads, out object[] stack_frames);
 
index 231b829c50947d22adcf4ea2a171ce85648ae8f3..124aacd130248c037dac8a37f8ced82b6e8962a4 100644 (file)
@@ -12,6 +12,7 @@ using System.Globalization;
 using System.IO;
 using System.Runtime.Serialization.Formatters.Binary;
 using System.Threading;
+using System.Threading.Tasks;
 
 using NUnit.Framework;
 
@@ -727,20 +728,37 @@ namespace MonoTests.System.Globalization
                }
 
                [Test]
-               public void DefaultThreadCurrentCultureAndNumberFormaters () {
+               public void DefaultThreadCurrentCultureIsIgnoredWhenCultureFlowsToThread ()
+               {
                        string us_str = null;
                        string br_str = null;
+
                        var thread = new Thread (() => {
                                CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US");
                                us_str = 100000.ToString ("C");
                                CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("pt-BR");
                                br_str = 100000.ToString ("C");
                        });
+
+                       var expected = 100000.ToString ("C");
+
                        thread.Start ();
                        thread.Join ();
                        CultureInfo.DefaultThreadCurrentCulture = null;
-                       Assert.AreEqual ("$100,000.00", us_str, "#1");
-                       Assert.AreEqual ("R$ 100.000,00", br_str, "#2");
+                       Assert.AreEqual (expected, us_str, "#1");
+                       Assert.AreEqual (expected, br_str, "#2");
+               }
+
+               [Test]
+               public void FlowCultureInfoFromParentThreadSinceNet46 ()
+               {
+                       Func<Task> f = async () => {
+                               Thread.CurrentThread.CurrentUICulture = new CultureInfo ("pt-BR");
+                               await Task.Yield ();
+                               Assert.AreEqual ("pt-BR", Thread.CurrentThread.CurrentUICulture.Name);
+                       };
+
+                       f ().Wait ();
                }
        }
 }
index b477f7bb686d3aa8758503ff45f1bce268e22855..d85cf9fb97643751787b80da2b208e0e89641c5c 100644 (file)
@@ -1081,7 +1081,6 @@ namespace System.Threading {
 
             dls.Store.SetData(slot, data);
         }
-#if !MONO
 
         // #threadCultureInfo
         //
@@ -1337,12 +1336,23 @@ namespace System.Threading {
         }
 
 #if! FEATURE_LEAK_CULTURE_INFO
+
+#if MONO
+        static void nativeInitCultureAccessors()
+        {
+            m_CurrentCulture = CultureInfo.ConstructCurrentCulture ();
+            m_CurrentUICulture = CultureInfo.ConstructCurrentUICulture ();
+        }
+#else
         [System.Security.SecurityCritical]  // auto-generated
         [ResourceExposure(ResourceScope.None)]
         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
         [SuppressUnmanagedCodeSecurity]
         private static extern void nativeInitCultureAccessors();
 #endif
+#endif
+
+#if !MONO
 
         /*=============================================================*/