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.
189 lines
4.7 KiB
189 lines
4.7 KiB
5 years ago
|
#if FAT
|
||
|
|
||
|
using System;
|
||
|
using System.Threading;
|
||
|
using LinqInternal.Core;
|
||
|
|
||
|
namespace LinqInternal.Threading.Needles
|
||
|
{
|
||
|
[Serializable]
|
||
|
[System.Diagnostics.DebuggerNonUserCode]
|
||
|
internal class LazyAction : Promise
|
||
|
{
|
||
|
[NonSerialized]
|
||
|
private Thread _runnerThread;
|
||
|
|
||
|
private Action _action;
|
||
|
|
||
|
public LazyAction()
|
||
|
: base(true)
|
||
|
{
|
||
|
_action = null;
|
||
|
}
|
||
|
|
||
|
public LazyAction(Action action)
|
||
|
: base(false)
|
||
|
{
|
||
|
if (action == null)
|
||
|
{
|
||
|
throw new ArgumentNullException("action");
|
||
|
}
|
||
|
_action = action;
|
||
|
}
|
||
|
|
||
|
public LazyAction(Action action, bool cacheExceptions)
|
||
|
: base(false)
|
||
|
{
|
||
|
if (action == null)
|
||
|
{
|
||
|
throw new ArgumentNullException("action");
|
||
|
}
|
||
|
_action = action;
|
||
|
if (cacheExceptions)
|
||
|
{
|
||
|
_action = () =>
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
action.Invoke();
|
||
|
}
|
||
|
catch (Exception exc)
|
||
|
{
|
||
|
_action = ActionHelper.GetThrowAction(exc);
|
||
|
throw;
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected Thread RunnerThread
|
||
|
{
|
||
|
get { return _runnerThread; }
|
||
|
}
|
||
|
|
||
|
public virtual void Execute()
|
||
|
{
|
||
|
if (_runnerThread == Thread.CurrentThread)
|
||
|
{
|
||
|
throw new InvalidOperationException();
|
||
|
}
|
||
|
var action = Interlocked.Exchange(ref _action, null);
|
||
|
if (action == null)
|
||
|
{
|
||
|
base.Wait();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ExecuteExtracted(action);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void ReleaseAction()
|
||
|
{
|
||
|
Volatile.Write(ref _action, null);
|
||
|
}
|
||
|
|
||
|
public override void Wait()
|
||
|
{
|
||
|
if (_runnerThread == Thread.CurrentThread)
|
||
|
{
|
||
|
throw new InvalidOperationException();
|
||
|
}
|
||
|
base.Wait();
|
||
|
}
|
||
|
|
||
|
public override void Wait(CancellationToken cancellationToken)
|
||
|
{
|
||
|
if (_runnerThread == Thread.CurrentThread)
|
||
|
{
|
||
|
throw new InvalidOperationException();
|
||
|
}
|
||
|
base.Wait(cancellationToken);
|
||
|
}
|
||
|
|
||
|
public override void Wait(int milliseconds)
|
||
|
{
|
||
|
if (_runnerThread == Thread.CurrentThread)
|
||
|
{
|
||
|
throw new InvalidOperationException();
|
||
|
}
|
||
|
base.Wait(milliseconds);
|
||
|
}
|
||
|
|
||
|
public override void Wait(TimeSpan timeout)
|
||
|
{
|
||
|
if (_runnerThread == Thread.CurrentThread)
|
||
|
{
|
||
|
throw new InvalidOperationException();
|
||
|
}
|
||
|
base.Wait(timeout);
|
||
|
}
|
||
|
|
||
|
public override void Wait(int milliseconds, CancellationToken cancellationToken)
|
||
|
{
|
||
|
if (_runnerThread == Thread.CurrentThread)
|
||
|
{
|
||
|
throw new InvalidOperationException();
|
||
|
}
|
||
|
base.Wait(milliseconds, cancellationToken);
|
||
|
}
|
||
|
|
||
|
public override void Wait(TimeSpan timeout, CancellationToken cancellationToken)
|
||
|
{
|
||
|
if (_runnerThread == Thread.CurrentThread)
|
||
|
{
|
||
|
throw new InvalidOperationException();
|
||
|
}
|
||
|
base.Wait(timeout, cancellationToken);
|
||
|
}
|
||
|
|
||
|
protected virtual void Execute(Action beforeInitialize)
|
||
|
{
|
||
|
if (beforeInitialize == null)
|
||
|
{
|
||
|
throw new ArgumentNullException("beforeInitialize");
|
||
|
}
|
||
|
if (_runnerThread == Thread.CurrentThread)
|
||
|
{
|
||
|
throw new InvalidOperationException();
|
||
|
}
|
||
|
var valueFactory = Interlocked.Exchange(ref _action, null);
|
||
|
if (valueFactory == null)
|
||
|
{
|
||
|
base.Wait();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
beforeInitialize.Invoke();
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
ExecuteExtracted(valueFactory);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void ExecuteExtracted(Action action)
|
||
|
{
|
||
|
_runnerThread = Thread.CurrentThread;
|
||
|
try
|
||
|
{
|
||
|
action.Invoke();
|
||
|
}
|
||
|
catch (Exception exception)
|
||
|
{
|
||
|
Interlocked.CompareExchange(ref _action, action, null);
|
||
|
SetError(exception);
|
||
|
throw;
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
_runnerThread = null;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|