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.
152 lines
4.0 KiB
152 lines
4.0 KiB
5 years ago
|
#if FAT
|
||
|
|
||
|
using System;
|
||
|
using System.Threading;
|
||
|
|
||
|
namespace LinqInternal.Threading.Needles
|
||
|
{
|
||
|
[Serializable]
|
||
|
[System.Diagnostics.DebuggerNonUserCode]
|
||
|
internal class FutureNeedle<T> : LazyNeedle<T>
|
||
|
{
|
||
|
private readonly Action<Action> _schedule;
|
||
|
private int _status;
|
||
|
|
||
|
public FutureNeedle(Func<T> valueFactory)
|
||
|
: base(valueFactory)
|
||
|
{
|
||
|
_schedule = Schedule;
|
||
|
}
|
||
|
|
||
|
public FutureNeedle(Func<T> valueFactory, bool autoSchedule)
|
||
|
: base(valueFactory)
|
||
|
{
|
||
|
_schedule = Schedule;
|
||
|
if (autoSchedule)
|
||
|
{
|
||
|
Schedule();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public FutureNeedle(Action<Action> schedule, Func<T> valueFactory)
|
||
|
: base(valueFactory)
|
||
|
{
|
||
|
_schedule = schedule;
|
||
|
}
|
||
|
|
||
|
public FutureNeedle(Action<Action> schedule, Func<T> valueFactory, bool autoSchedule)
|
||
|
: base(valueFactory)
|
||
|
{
|
||
|
_schedule = schedule;
|
||
|
if (autoSchedule)
|
||
|
{
|
||
|
Schedule();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override void Initialize()
|
||
|
{
|
||
|
if (Interlocked.CompareExchange(ref _status, 1, 0) != 0)
|
||
|
{
|
||
|
base.Wait();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
base.Initialize();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected override void Initialize(Action beforeInitialize)
|
||
|
{
|
||
|
if (Interlocked.CompareExchange(ref _status, 1, 0) != 0)
|
||
|
{
|
||
|
base.Wait();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
base.Initialize(beforeInitialize);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public bool Schedule()
|
||
|
{
|
||
|
if (Interlocked.CompareExchange(ref _status, 1, 0) != 0)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
_schedule(base.Initialize);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public override void Wait()
|
||
|
{
|
||
|
Initialize();
|
||
|
}
|
||
|
|
||
|
public override void Wait(CancellationToken cancellationToken)
|
||
|
{
|
||
|
if (Interlocked.CompareExchange(ref _status, 1, 0) != 0)
|
||
|
{
|
||
|
base.Wait(cancellationToken);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
base.Initialize();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override void Wait(int milliseconds)
|
||
|
{
|
||
|
if (Interlocked.CompareExchange(ref _status, 1, 0) != 0)
|
||
|
{
|
||
|
base.Wait(milliseconds);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
var start = ThreadingHelper.TicksNow();
|
||
|
base.Initialize();
|
||
|
milliseconds -= (int)ThreadingHelper.Milliseconds(ThreadingHelper.TicksNow() - start);
|
||
|
if (milliseconds > 0)
|
||
|
{
|
||
|
base.Wait(milliseconds);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override void Wait(TimeSpan timeout)
|
||
|
{
|
||
|
Wait((int)timeout.TotalMilliseconds);
|
||
|
}
|
||
|
|
||
|
public override void Wait(int milliseconds, CancellationToken cancellationToken)
|
||
|
{
|
||
|
if (Interlocked.CompareExchange(ref _status, 1, 0) != 0)
|
||
|
{
|
||
|
base.Wait(milliseconds, cancellationToken);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
var start = ThreadingHelper.TicksNow();
|
||
|
base.Initialize();
|
||
|
milliseconds -= (int)ThreadingHelper.Milliseconds(ThreadingHelper.TicksNow() - start);
|
||
|
if (milliseconds > 0)
|
||
|
{
|
||
|
base.Wait(milliseconds, cancellationToken);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override void Wait(TimeSpan timeout, CancellationToken cancellationToken)
|
||
|
{
|
||
|
Wait((int)timeout.TotalMilliseconds, cancellationToken);
|
||
|
}
|
||
|
|
||
|
private static void Schedule(Action action)
|
||
|
{
|
||
|
var waitCallback = new WaitCallback(_ => action());
|
||
|
ThreadPool.QueueUserWorkItem(waitCallback);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|