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;
IPrincipal principal;
int principal_version;
+ bool current_culture_set;
+ bool current_ui_culture_set;
CultureInfo current_culture;
CultureInfo current_ui_culture;
[ThreadStatic]
static ExecutionContext _ec;
+ 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;
return (int)(CurrentThread.internal_thread.thread_id);
}
}
-
- // Stores a hash keyed by strings of LocalDataStoreSlot objects
- static Dictionary<string, LocalDataStoreSlot> datastorehash;
- private static object datastore_lock = new object ();
- private static void InitDataStoreHash () {
- lock (datastore_lock) {
- if (datastorehash == null) {
- datastorehash = new Dictionary<string, LocalDataStoreSlot> ();
- }
+ static NamedDataSlot NamedDataSlot {
+ get {
+ if (namedDataSlot == null)
+ Interlocked.CompareExchange (ref namedDataSlot, new NamedDataSlot (), null);
+
+ return namedDataSlot;
}
}
- public static LocalDataStoreSlot AllocateNamedDataSlot (string name) {
- lock (datastore_lock) {
- if (datastorehash == null)
- InitDataStoreHash ();
-
- if (datastorehash.ContainsKey (name)) {
- // This exception isnt documented (of
- // course) but .net throws it
- throw new ArgumentException("Named data slot already added");
- }
-
- var slot = AllocateDataSlot ();
-
- datastorehash.Add (name, slot);
-
- return slot;
- }
+ public static LocalDataStoreSlot AllocateNamedDataSlot (string name)
+ {
+ return NamedDataSlot.Allocate (name);
}
- public static void FreeNamedDataSlot (string name) {
- lock (datastore_lock) {
- if (datastorehash == null)
- InitDataStoreHash ();
-
- if (datastorehash.ContainsKey (name)) {
- datastorehash.Remove (name);
- }
- }
+ public static void FreeNamedDataSlot (string name)
+ {
+ NamedDataSlot.Free (name);
}
- public static LocalDataStoreSlot AllocateDataSlot () {
+ public static LocalDataStoreSlot AllocateDataSlot ()
+ {
return new LocalDataStoreSlot (true);
}
[MethodImplAttribute (MethodImplOptions.InternalCall)]
internal extern static void FreeLocalSlotValues (int slot, bool thread_local);
- public static LocalDataStoreSlot GetNamedDataSlot(string name) {
- lock (datastore_lock) {
- if (datastorehash == null)
- InitDataStoreHash ();
-
- LocalDataStoreSlot slot;
- if (!datastorehash.TryGetValue (name, out slot)) {
- slot=AllocateNamedDataSlot(name);
- }
-
- return slot;
- }
+ public static LocalDataStoreSlot GetNamedDataSlot(string name)
+ {
+ return NamedDataSlot.Get (name);
}
public static AppDomain GetDomain() {
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)]
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;
}
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;
}
if (value == null)
throw new ArgumentNullException ("value");
current_ui_culture = value;
+ current_ui_culture_set = true;
}
}
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);
}
}
[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 ()
{
}
}
-#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;
((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,
[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)
{
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)
Internal.stack_size = CheckStackSize (maxStackSize);
}
- [MonoTODO ("limited to CompressedStack support")]
public ExecutionContext ExecutionContext {
[ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
get {
_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 {
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;
throw new NotImplementedException ();
}
#endif
+
+ internal CultureInfo GetCurrentUICultureNoAppX ()
+ {
+ return CultureInfo.CurrentUICulture;
+ }
}
}