Merge pull request #901 from Blewzman/FixAggregateExceptionGetBaseException
[mono.git] / mcs / class / corlib / System.Threading / Monitor.cs
index aea57b5b8dda5285aa0b8c0c2564c4543eb514d0..d6a289e76b5a1754dfb0cc08774185b39a13d62a 100644 (file)
 
 using System.Runtime.CompilerServices;
 using System.Runtime.Remoting.Contexts;
-
-#if NET_2_0
 using System.Runtime.ConstrainedExecution;
-#endif
+using System.Runtime.InteropServices;
 
 namespace System.Threading
 {
-       public sealed class Monitor
+       [ComVisible (true)]
+       public static class Monitor
        {
-               private Monitor () {}
-
                // Grabs the mutex on object 'obj', with a maximum
                // wait time 'ms' but doesn't block - if it can't get
                // the lock it returns false, true if it can
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                private extern static bool Monitor_try_enter(object obj, int ms);
 
-               public static void Enter(object obj) {
-                       if(obj==null) {
-                               throw new ArgumentNullException("obj");
-                       }
-                       //if(obj.GetType().IsValueType==true) {
-                       //      throw new ArgumentException("Value type");
-                       //}
-
-                       Monitor_try_enter(obj, Timeout.Infinite);
-               }
+               // Enter/Exit are implemented directly as icalls for performance reasons
 
-               // Releases the mutex on object 'obj'
+               // Acquires the mutex on object 'obj'
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               private extern static void Monitor_exit(object obj);
+               public extern static void Enter(object obj);
 
-#if NET_2_0
+               // Releases the mutex on object 'obj'
                [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
-#endif
-               public static void Exit(object obj) {
-                       if(obj==null) {
-                               throw new ArgumentNullException("obj");
-                       }
-                       //if(obj.GetType().IsValueType==true) {
-                       //      throw new ArgumentException("Value type");
-                       //}
-
-                       Monitor_exit(obj);
-               }
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               public extern static void Exit(object obj);
 
                // Signals one of potentially many objects waiting on
                // object 'obj'
@@ -114,61 +93,34 @@ namespace System.Threading
                        Monitor_pulse_all(obj);
                }
 
-               public static bool TryEnter(object obj) {
-                       if(obj==null) {
-                               throw new ArgumentNullException("obj");
-                       }
-                       //if(obj.GetType().IsValueType==true) {
-                       //      throw new ArgumentException("Value type");
-                       //}
-                       
-                       return(Monitor_try_enter(obj, 0));
+               public static bool TryEnter (object obj)
+               {
+                       return TryEnter (obj, 0);
                }
 
-               public static bool TryEnter(object obj, int millisecondsTimeout) {
-                       if(obj==null) {
-                               throw new ArgumentNullException("obj");
-                       }
-                       //if(obj.GetType().IsValueType==true) {
-                       //      throw new ArgumentException("Value type");
-                       //}
-
-                       // LAMESPEC: should throw an exception when ms<0, but
-                       // Timeout.Infinite is -1
-                       if(millisecondsTimeout == Timeout.Infinite) {
-                               Enter(obj);
-                               return(true);
-                       }
-                       
-                       if(millisecondsTimeout<0) {
-                               throw new ArgumentException("millisecondsTimeout", "negative value for millisecondsTimeout");
-                       }
-                       
-                       return(Monitor_try_enter(obj, millisecondsTimeout));
-               }
+               public static bool TryEnter (object obj, int millisecondsTimeout)
+               {
+                       if (obj == null)
+                               throw new ArgumentNullException ("obj");
 
-               public static bool TryEnter(object obj, TimeSpan timeout) {
-                       if(obj==null) {
-                               throw new ArgumentNullException("obj");
+                       if (millisecondsTimeout == Timeout.Infinite) {
+                               Enter (obj);
+                               return true;
                        }
-                       //if(obj.GetType().IsValueType==true) {
-                       //      throw new ArgumentException("Value type");
-                       //}
 
-                       // LAMESPEC: should throw an exception when ms<0, but
-                       // Timeout.Infinite is -1
-                       int ms=Convert.ToInt32(timeout.TotalMilliseconds);
+                       if (millisecondsTimeout < 0)
+                               throw new ArgumentException ("negative value for millisecondsTimeout", "millisecondsTimeout");
                        
-                       if(ms == Timeout.Infinite) {
-                               Enter(obj);
-                               return(true);
-                       }
+                       return Monitor_try_enter (obj, millisecondsTimeout);
+               }
 
-                       if(ms < 0 || ms > Int32.MaxValue) {
-                               throw new ArgumentOutOfRangeException("timeout", "timeout out of range");
-                       }
+               public static bool TryEnter (object obj, TimeSpan timeout)
+               {
+                       long ms = (long) timeout.TotalMilliseconds;
+                       if (ms < Timeout.Infinite || ms > Int32.MaxValue)
+                               throw new ArgumentOutOfRangeException ("timeout", "timeout out of range");
                        
-                       return(Monitor_try_enter(obj, ms));
+                       return TryEnter (obj, (int) ms);
                }
 
                // Waits for a signal on object 'obj' with maximum
@@ -177,50 +129,43 @@ namespace System.Threading
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                private extern static bool Monitor_wait(object obj, int ms);
 
-               public static bool Wait(object obj) {
-                       if(obj==null) {
-                               throw new ArgumentNullException("obj");
-                       }
-                       if(Monitor_test_synchronised(obj)==false) {
-                               throw new SynchronizationLockException("Object is not synchronized");
-                       }
-
-                       return(Monitor_wait(obj, Timeout.Infinite));
+               public static bool Wait (object obj)
+               {
+                       return Wait (obj, Timeout.Infinite);
                }
 
-               public static bool Wait(object obj, int millisecondsTimeout) {
-                       if(obj==null) {
-                               throw new ArgumentNullException("obj");
-                       }
-                       if(Monitor_test_synchronised(obj)==false) {
-                               throw new SynchronizationLockException("Object is not synchronized");
-                       }
-                       if (millisecondsTimeout < 0 && millisecondsTimeout != Timeout.Infinite)
+               public static bool Wait (object obj, int millisecondsTimeout)
+               {
+                       if (obj == null)
+                               throw new ArgumentNullException ("obj");
+
+                       if (millisecondsTimeout < Timeout.Infinite)
                                throw new ArgumentOutOfRangeException ("millisecondsTimeout", "timeout out of range");
 
-                       return(Monitor_wait(obj, millisecondsTimeout));
+                       if (!Monitor_test_synchronised (obj))
+                               throw new SynchronizationLockException ("Object is not synchronized");
+
+                       return Monitor_wait (obj, millisecondsTimeout);
                }
 
-               public static bool Wait(object obj, TimeSpan timeout) {
-                       if(obj==null) {
-                               throw new ArgumentNullException("obj");
-                       }
-                       // LAMESPEC: says to throw ArgumentException too
-                       int ms=Convert.ToInt32(timeout.TotalMilliseconds);
-                       
-                       if((ms < 0 && ms != Timeout.Infinite) || ms > Int32.MaxValue) {
-                               throw new ArgumentOutOfRangeException("timeout", "timeout out of range");
-                       }
-                       if(Monitor_test_synchronised(obj)==false) {
-                               throw new SynchronizationLockException("Object is not synchronized");
-                       }
+               public static bool Wait (object obj, TimeSpan timeout)
+               {
+                       long ms = (long) timeout.TotalMilliseconds;
+                       if (ms < Timeout.Infinite || ms > Int32.MaxValue)
+                               throw new ArgumentOutOfRangeException ("timeout", "timeout out of range");
 
-                       return(Monitor_wait(obj, ms));
+                       return Wait (obj, (int) ms);
                }
 
                public static bool Wait(object obj, int millisecondsTimeout, bool exitContext) {
                        try {
-                               if (exitContext) SynchronizationAttribute.ExitContext ();
+                               if (exitContext) {
+#if MONOTOUCH
+                                       throw new NotSupportedException ("exitContext == true is not supported");
+#else
+                                       SynchronizationAttribute.ExitContext ();
+#endif
+                               }
                                return Wait (obj, millisecondsTimeout);
                        }
                        finally {
@@ -230,12 +175,65 @@ namespace System.Threading
 
                public static bool Wait(object obj, TimeSpan timeout, bool exitContext) {
                        try {
-                               if (exitContext) SynchronizationAttribute.ExitContext ();
+                               if (exitContext) {
+#if MONOTOUCH
+                                       throw new NotSupportedException ("exitContext == true is not supported");
+#else
+                                       SynchronizationAttribute.ExitContext ();
+#endif
+                               }
                                return Wait (obj, timeout);
                        }
                        finally {
                                if (exitContext) SynchronizationAttribute.EnterContext ();
                        }
                }
+
+#if NET_4_0
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               extern static void try_enter_with_atomic_var (object obj, int millisecondsTimeout, ref bool lockTaken);
+
+               public static void Enter (object obj, ref bool lockTaken)
+               {
+                       TryEnter (obj, Timeout.Infinite, ref lockTaken);
+               }
+
+               public static void TryEnter (object obj, ref bool lockTaken)
+               {
+                       TryEnter (obj, 0, ref lockTaken);
+               }
+
+               public static void TryEnter (object obj, TimeSpan timeout, ref bool lockTaken)
+               {
+                       long ms = (long) timeout.TotalMilliseconds;
+                       if (ms < Timeout.Infinite || ms > Int32.MaxValue)
+                               throw new ArgumentOutOfRangeException ("timeout", "timeout out of range");
+                       TryEnter (obj, (int)ms, ref lockTaken);
+               }
+
+               public static void TryEnter (object obj, int millisecondsTimeout, ref bool lockTaken)
+               {
+                       if (obj == null)
+                               throw new ArgumentNullException ("obj");
+                       if (lockTaken)
+                               throw new ArgumentException ("lockTaken");
+
+                       if (millisecondsTimeout < 0 && millisecondsTimeout != Timeout.Infinite)
+                               throw new ArgumentException ("negative value for millisecondsTimeout", "millisecondsTimeout");
+
+                       try_enter_with_atomic_var (obj, millisecondsTimeout, ref lockTaken);
+               }               
+
+#endif
+
+#if NET_4_5
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               extern static bool Monitor_test_owner (object obj);
+               
+               public static bool IsEntered (object obj)
+               {
+                       return Monitor_test_owner(obj);
+               }
+#endif
        }
 }