Having two concurrent operations of Set/Reset who succeeded in fetching the handle before it was disabled all the while trying to dispose may have caused a early release of the handle.
ManualResetEvent handle;
internal AtomicBooleanValue disposed;
- bool used;
+ int used;
bool set;
public ManualResetEventSlim ()
set = false;
Thread.MemoryBarrier ();
if (handle != null) {
- used = true;
+ Interlocked.Increment (ref used);
Thread.MemoryBarrier ();
var tmpHandle = handle;
if (tmpHandle != null)
tmpHandle.Reset ();
Thread.MemoryBarrier ();
- used = false;
+ Interlocked.Decrement (ref used);
}
}
set = true;
Thread.MemoryBarrier ();
if (handle != null) {
- used = true;
+ Interlocked.Increment (ref used);
Thread.MemoryBarrier ();
var tmpHandle = handle;
if (tmpHandle != null)
tmpHandle.Set ();
Thread.MemoryBarrier ();
- used = false;
+ Interlocked.Decrement (ref used);
}
}
if (handle != null) {
var tmpHandle = Interlocked.Exchange (ref handle, null);
- if (used) {
+ if (used > 0) {
// A tiny wait (just a few cycles normally) before releasing
SpinWait wait = new SpinWait ();
- while (used)
+ while (used > 0)
wait.SpinOnce ();
}
tmpHandle.Dispose ();