2007-01-03 Miguel de Icaza <miguel@novell.com>
authorMiguel de Icaza <miguel@gnome.org>
Wed, 3 Jan 2007 19:50:44 +0000 (19:50 -0000)
committerMiguel de Icaza <miguel@gnome.org>
Wed, 3 Jan 2007 19:50:44 +0000 (19:50 -0000)
* SafeHandle.cs: Do not use locks in SafeHandle to protect the
access to the refcount, use Interlocked.CompareExchange.  The
locks were the source of problems with domain finalization when
this code was enabled.

This should fix Matt Hargett's bug report with a full `make check'
that reported variations of:

** (../../class/lib/net_2_0/nunit-console.exe:29644): WARNING **:
Finalization of domain <domainname> timed out.

Also, it is a lot lighther.

svn path=/trunk/mcs/; revision=70433

mcs/class/corlib/System.Runtime.InteropServices/ChangeLog
mcs/class/corlib/System.Runtime.InteropServices/SafeHandle.cs

index 52558bc59621f66bf9118c3477f471b3f4b425c0..aee47a3d6c1e1cc614b7f156d970388e8464922a 100644 (file)
@@ -1,3 +1,18 @@
+2007-01-03  Miguel de Icaza  <miguel@novell.com>
+
+       * SafeHandle.cs: Do not use locks in SafeHandle to protect the
+       access to the refcount, use Interlocked.CompareExchange.  The
+       locks were the source of problems with domain finalization when
+       this code was enabled.
+
+       This should fix Matt Hargett's bug report with a full `make check'
+       that reported variations of:
+
+       ** (../../class/lib/net_2_0/nunit-console.exe:29644): WARNING **:
+       Finalization of domain <domainname> timed out.
+
+       Also, it is a lot lighther.
+
 2006-12-21  Miguel de Icaza  <miguel@novell.com>
 
        * CriticalHandle.cs: Add Dispose(bool disposing) method, and
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;
                        }
                }