merged Sys.Web.Services 2.0 support in my branch:
[mono.git] / mcs / class / corlib / System.Runtime.InteropServices / SafeHandle.cs
index 438bb7998bfd158cee47c7bcc23ec86e86142264..8825118ecb83e6e06b849df27427131a5ef4fb0b 100644 (file)
 //     find out whether the runtime performs the P/Invoke if the
 //     handle has been disposed already.
 //
+//
 
 #if NET_2_0
 using System;
 using System.Runtime.InteropServices;
 using System.Runtime.ConstrainedExecution;
+using System.Threading;
 
 namespace System.Runtime.InteropServices
 {
@@ -56,7 +58,6 @@ namespace System.Runtime.InteropServices
                // MonoSafeHandle
                //
                protected IntPtr handle;
-               object handle_lock = new object ();
                IntPtr invalid_handle_value;
                int refcount = 0;
                bool owns_handle;
@@ -73,12 +74,15 @@ namespace System.Runtime.InteropServices
                        if (refcount == 0)
                                throw new ObjectDisposedException (GetType ().FullName);
 
-                       lock (handle_lock){
-                               refcount--;
-                               if (refcount == 0 && owns_handle){
-                                       ReleaseHandle ();
-                                       handle = invalid_handle_value;
-                               }
+                       int newcount, current;
+                       do {
+                               current = refcount;
+                               newcount = current-1;
+                       } while (Interlocked.CompareExchange (ref refcount, newcount, current) != current);
+
+                       if (newcount == 0 && owns_handle){
+                               ReleaseHandle ();
+                               handle = invalid_handle_value;
                        }
                }
 
@@ -96,8 +100,12 @@ namespace System.Runtime.InteropServices
                        if (refcount == 0)
                                throw new ObjectDisposedException (GetType ().FullName);
 
-                       lock (handle_lock){
-                               if (handle == invalid_handle_value || refcount == 0){
+                       int newcount, current;
+                       do {
+                               current = refcount;
+                               newcount = current + 1;
+                               
+                               if (handle == invalid_handle_value || current == 0){
                                        //
                                        // In MS, calling sf.Close () followed by a call
                                        // to P/Invoke with SafeHandles throws this, but
@@ -106,10 +114,8 @@ namespace System.Runtime.InteropServices
                                        //
                                        throw new ObjectDisposedException (GetType ().FullName);
                                }
-                               
-                               refcount++;
-                               success = true;
-                       }
+                       } while (Interlocked.CompareExchange (ref refcount, newcount, current) != current);
+                       success = true;
                }
 
                public IntPtr DangerousGetHandle ()
@@ -126,12 +132,15 @@ namespace System.Runtime.InteropServices
                        if (refcount == 0)
                                throw new ObjectDisposedException (GetType ().FullName);
 
-                       lock (handle_lock){
-                               refcount--;
-                               if (refcount == 0 && owns_handle){
-                                       ReleaseHandle ();
-                                       handle = invalid_handle_value;
-                               }
+                       int newcount, current;
+                       do {
+                               current = refcount;
+                               newcount = current-1;
+                       } while (Interlocked.CompareExchange (ref refcount, newcount, current) != current);
+
+                       if (newcount == 0 && owns_handle){
+                               ReleaseHandle ();
+                               handle = invalid_handle_value;
                        }
                }