网上演练
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

257 lines
6.7 KiB

// Needed for Workaround
#if !NET_4_6
using System;
using System.Threading;
namespace LinqInternal.Threading.Needles
{
[Serializable]
[System.Diagnostics.DebuggerNonUserCode]
internal class Promise : IWaitablePromise
{
private readonly int _hashCode;
private Exception _exception;
private StructNeedle<ManualResetEventSlim> _waitHandle;
public Promise(bool done)
{
_exception = null;
_hashCode = base.GetHashCode();
if (!done)
{
_waitHandle = new ManualResetEventSlim(false);
}
}
public Promise(Exception exception)
{
_exception = exception;
_hashCode = exception.GetHashCode();
_waitHandle = new ManualResetEventSlim(true);
}
~Promise()
{
ReleaseWaitHandle(false);
}
public Exception Exception
{
get { return _exception; }
}
bool IPromise.IsCanceled
{
get { return false; }
}
public bool IsCompleted
{
get
{
var waitHandle = _waitHandle.Value;
return waitHandle == null || waitHandle.IsSet;
}
}
public bool IsFaulted
{
get { return _exception != null; }
}
protected IRecyclableNeedle<ManualResetEventSlim> WaitHandle
{
get { return _waitHandle; }
}
public virtual void Free()
{
var waitHandle = _waitHandle.Value;
if (waitHandle == null)
{
_waitHandle.Value = new ManualResetEventSlim(false);
}
else
{
waitHandle.Reset();
}
_exception = null;
}
public virtual void Free(Action beforeFree)
{
if (beforeFree == null)
{
throw new ArgumentNullException("beforeFree");
}
var waitHandle = _waitHandle.Value;
if (waitHandle == null || waitHandle.IsSet)
{
try
{
beforeFree();
}
finally
{
if (waitHandle == null)
{
_waitHandle.Value = new ManualResetEventSlim(false);
}
else
{
waitHandle.Reset();
}
_exception = null;
}
}
else
{
waitHandle.Reset();
_exception = null;
}
}
public override int GetHashCode()
{
return _hashCode;
}
public void SetCompleted()
{
_exception = null;
ReleaseWaitHandle(true);
}
public void SetError(Exception error)
{
_exception = error;
ReleaseWaitHandle(true);
}
public override string ToString()
{
return IsCompleted
? (_exception == null
? "[Done]"
: _exception.ToString())
: "[Not Created]";
}
public virtual void Wait()
{
var waitHandle = _waitHandle.Value;
if (waitHandle != null)
{
try
{
waitHandle.Wait();
}
catch (ObjectDisposedException exception)
{
// Came late to the party, initialization was done
GC.KeepAlive(exception);
}
}
}
public virtual void Wait(CancellationToken cancellationToken)
{
var waitHandle = _waitHandle.Value;
if (waitHandle != null)
{
try
{
waitHandle.Wait(cancellationToken);
}
catch (ObjectDisposedException exception)
{
// Came late to the party, initialization was done
GC.KeepAlive(exception);
}
}
}
public virtual void Wait(int milliseconds)
{
var waitHandle = _waitHandle.Value;
if (waitHandle != null)
{
try
{
waitHandle.Wait(milliseconds);
}
catch (ObjectDisposedException exception)
{
// Came late to the party, initialization was done
GC.KeepAlive(exception);
}
}
}
public virtual void Wait(TimeSpan timeout)
{
var waitHandle = _waitHandle.Value;
if (waitHandle != null)
{
try
{
waitHandle.Wait(timeout);
}
catch (ObjectDisposedException exception)
{
// Came late to the party, initialization was done
GC.KeepAlive(exception);
}
}
}
public virtual void Wait(int milliseconds, CancellationToken cancellationToken)
{
var waitHandle = _waitHandle.Value;
if (waitHandle != null)
{
try
{
waitHandle.Wait(milliseconds, cancellationToken);
}
catch (ObjectDisposedException exception)
{
// Came late to the party, initialization was done
GC.KeepAlive(exception);
}
}
}
public virtual void Wait(TimeSpan timeout, CancellationToken cancellationToken)
{
var waitHandle = _waitHandle.Value;
if (waitHandle != null)
{
try
{
waitHandle.Wait(timeout, cancellationToken);
}
catch (ObjectDisposedException exception)
{
// Came late to the party, initialization was done
GC.KeepAlive(exception);
}
}
}
protected void ReleaseWaitHandle(bool done)
{
var waitHandle = _waitHandle.Value;
if (waitHandle != null)
{
if (done)
{
waitHandle.Set();
}
waitHandle.Dispose();
}
_waitHandle.Value = null;
}
}
}
#endif