#if FAT using System; using System.Threading; namespace LinqInternal.Threading.Needles { [Serializable] [System.Diagnostics.DebuggerNonUserCode] internal class FutureNeedle : LazyNeedle { private readonly Action _schedule; private int _status; public FutureNeedle(Func valueFactory) : base(valueFactory) { _schedule = Schedule; } public FutureNeedle(Func valueFactory, bool autoSchedule) : base(valueFactory) { _schedule = Schedule; if (autoSchedule) { Schedule(); } } public FutureNeedle(Action schedule, Func valueFactory) : base(valueFactory) { _schedule = schedule; } public FutureNeedle(Action schedule, Func 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