+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
// 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
{
// MonoSafeHandle
//
protected IntPtr handle;
- object handle_lock = new object ();
IntPtr invalid_handle_value;
int refcount = 0;
bool owns_handle;
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;
}
}
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
//
throw new ObjectDisposedException (GetType ().FullName);
}
-
- refcount++;
- success = true;
- }
+ } while (Interlocked.CompareExchange (ref refcount, newcount, current) != current);
+ success = true;
}
public IntPtr DangerousGetHandle ()
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;
}
}