Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 36 additions & 14 deletions mcs/class/corlib/System.Runtime.InteropServices/SafeHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@
// For details, see:
// http://blogs.msdn.com/cbrumme/archive/2004/02/20/77460.aspx
//
// CER-like behavior is implemented for Close and DangerousAddRef
// via the try/finally uninterruptible pattern in case of async
// exceptions like ThreadAbortException.
//
// On implementing SafeHandles:
// http://blogs.msdn.com/bclteam/archive/2005/03/15/396335.aspx
//
// Issues:
// The System.Runtime.ConstrainedExecution.ReliabilityContractAttribute has
// not been applied to any APIs here yet.
//
// TODO: Although DangerousAddRef has been implemented, I need to
// find out whether the runtime performs the P/Invoke if the
Expand All @@ -46,6 +48,7 @@
using System;
using System.Runtime.InteropServices;
using System.Runtime.ConstrainedExecution;
using System.Runtime.CompilerServices;
using System.Threading;

namespace System.Runtime.InteropServices
Expand Down Expand Up @@ -81,16 +84,27 @@ public void Close ()
if (refcount == 0)
throw new ObjectDisposedException (GetType ().FullName);

int newcount, current;
do {
current = refcount;
newcount = current-1;
} while (Interlocked.CompareExchange (ref refcount, newcount, current) != current);

if (newcount == 0 && owns_handle && !IsInvalid){
ReleaseHandle ();
handle = invalid_handle_value;
refcount = -1;
int newcount = 0, current = 0;
bool registered = false;
RuntimeHelpers.PrepareConstrainedRegions ();
try {
do {
current = refcount;
newcount = current-1;

// See notes for explanation
try {}
finally {
if (Interlocked.CompareExchange (ref refcount, newcount, current) == current)
registered = true;
}
} while (!registered);
} finally {
if (registered && newcount == 0 && owns_handle && !IsInvalid){
ReleaseHandle ();
handle = invalid_handle_value;
refcount = -1;
}
}
}

Expand All @@ -109,6 +123,7 @@ public void DangerousAddRef (ref bool success)
if (refcount <= 0)
throw new ObjectDisposedException (GetType ().FullName);

bool registered = false;
int newcount, current;
do {
current = refcount;
Expand All @@ -123,8 +138,15 @@ public void DangerousAddRef (ref bool success)
//
throw new ObjectDisposedException (GetType ().FullName);
}
} while (Interlocked.CompareExchange (ref refcount, newcount, current) != current);
success = true;

// See notes for explanations
RuntimeHelpers.PrepareConstrainedRegions ();
try {}
finally {
if (Interlocked.CompareExchange (ref refcount, newcount, current) == current)
registered = success = true;
}
} while (!registered);
}

[ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
Expand Down