New tests.
[mono.git] / mcs / class / corlib / System.Runtime.InteropServices / SafeHandle.cs
index 8825118ecb83e6e06b849df27427131a5ef4fb0b..e1b0a70ffb24ddc408c4b20af7f1c0b81ae2814f 100644 (file)
@@ -43,7 +43,6 @@
 //
 //
 
-#if NET_2_0
 using System;
 using System.Runtime.InteropServices;
 using System.Runtime.ConstrainedExecution;
@@ -62,6 +61,13 @@ namespace System.Runtime.InteropServices
                int refcount = 0;
                bool owns_handle;
                
+#if NET_2_1
+               protected SafeHandle ()
+               {
+                       throw new NotImplementedException ();
+               }
+#endif
+               [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
                protected SafeHandle (IntPtr invalidHandleValue, bool ownsHandle)
                {
                        invalid_handle_value = invalidHandleValue;
@@ -69,6 +75,7 @@ namespace System.Runtime.InteropServices
                        refcount = 1;
                }
 
+               [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
                public void Close ()
                {
                        if (refcount == 0)
@@ -80,9 +87,10 @@ namespace System.Runtime.InteropServices
                                newcount = current-1;
                        } while (Interlocked.CompareExchange (ref refcount, newcount, current) != current);
 
-                       if (newcount == 0 && owns_handle){
+                       if (newcount == 0 && owns_handle && !IsInvalid){
                                ReleaseHandle ();
                                handle = invalid_handle_value;
+                               refcount = -1;
                        }
                }
 
@@ -95,9 +103,10 @@ namespace System.Runtime.InteropServices
                // try { x.DangerousAddRef (ref release); ... }
                // finally { if (release) x.DangerousRelease (); }
                //
+               [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
                public void DangerousAddRef (ref bool success)
                {
-                       if (refcount == 0)
+                       if (refcount <= 0)
                                throw new ObjectDisposedException (GetType ().FullName);
 
                        int newcount, current;
@@ -105,7 +114,7 @@ namespace System.Runtime.InteropServices
                                current = refcount;
                                newcount = current + 1;
                                
-                               if (handle == invalid_handle_value || current == 0){
+                               if (current <= 0){
                                        //
                                        // In MS, calling sf.Close () followed by a call
                                        // to P/Invoke with SafeHandles throws this, but
@@ -118,18 +127,20 @@ namespace System.Runtime.InteropServices
                        success = true;
                }
 
+               [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
                public IntPtr DangerousGetHandle ()
                {
-                       if (refcount == 0){
+                       if (refcount <= 0){
                                throw new ObjectDisposedException (GetType ().FullName);
                        }
 
                        return handle;
                }
 
+               [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
                public void DangerousRelease ()
                {
-                       if (refcount == 0)
+                       if (refcount <= 0)
                                throw new ObjectDisposedException (GetType ().FullName);
 
                        int newcount, current;
@@ -138,13 +149,14 @@ namespace System.Runtime.InteropServices
                                newcount = current-1;
                        } while (Interlocked.CompareExchange (ref refcount, newcount, current) != current);
 
-                       if (newcount == 0 && owns_handle){
+                       if (newcount == 0 && owns_handle && !IsInvalid){
                                ReleaseHandle ();
                                handle = invalid_handle_value;
                        }
                }
 
-               public virtual void Dispose ()
+               [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
+               public void Dispose ()
                {
                        Dispose (true);
                        GC.SuppressFinalize (this);
@@ -154,11 +166,13 @@ namespace System.Runtime.InteropServices
                // See documentation, this invalidates the handle without
                // closing it.
                //
+               [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
                public void SetHandleAsInvalid ()
                {
                        handle = invalid_handle_value;
                }
                
+               [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
                protected virtual void Dispose (bool disposing)
                {
                        if (disposing)
@@ -173,30 +187,33 @@ namespace System.Runtime.InteropServices
                        }
                }
 
+               [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
                protected abstract bool ReleaseHandle ();
 
+               [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
                protected void SetHandle (IntPtr handle)
                {
                        this.handle = handle;
                }
 
                public bool IsClosed {
+                       [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
                        get {
-                               return refcount == 0;
+                               return refcount <= 0;
                        }
                }
 
                public abstract bool IsInvalid {
+                       [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
                        get;
                }
 
                ~SafeHandle ()
                {
-                       if (owns_handle){
+                       if (owns_handle && !IsInvalid){
                                ReleaseHandle ();
                                handle = invalid_handle_value;
                        }
                }
        }
 }
-#endif