Future
Represents lightweight version of Task.
using System;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
namespace DotNext.Threading.Tasks
{
public abstract class Future : IFuture, INotifyCompletion
{
public interface IAwaiter : IFuture, INotifyCompletion
{
void GetResult();
}
public interface IAwaiter<[System.Runtime.CompilerServices.Nullable(2)] out TResult> : IFuture, INotifyCompletion
{
[System.Runtime.CompilerServices.NullableContext(1)]
TResult GetResult();
}
protected sealed class IncompletedFutureException : InvalidOperationException
{
}
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
private sealed class Continuation
{
private readonly Action callback;
private readonly object context;
private Continuation(Action callback, SynchronizationContext context)
{
this.callback = callback;
this.context = context;
}
private Continuation(Action callback, TaskScheduler scheduler)
{
this.callback = callback;
context = scheduler;
}
private void Invoke()
{
object obj = context;
SynchronizationContext synchronizationContext = obj as SynchronizationContext;
if (synchronizationContext == null) {
TaskScheduler taskScheduler = obj as TaskScheduler;
if (taskScheduler != null)
Task.Factory.StartNew(callback, CancellationToken.None, TaskCreationOptions.DenyChildAttach, taskScheduler);
else
callback();
} else
callback.InvokeInContext(synchronizationContext);
}
internal static Action Create(Action callback)
{
SynchronizationContext synchronizationContext = SynchronizationContext.Current?.CreateCopy();
if (synchronizationContext != null)
return new Continuation(callback, synchronizationContext).Invoke;
TaskScheduler current = TaskScheduler.Current;
if (current == TaskScheduler.Default)
return callback.InvokeInThreadPool;
return new Continuation(callback, current).Invoke;
}
}
private readonly bool runContinuationsAsynchronously;
[System.Runtime.CompilerServices.Nullable(2)]
private Action continuation;
public abstract bool IsCompleted { get; }
protected Future(bool runContinuationsAsynchronously = true)
{
this.runContinuationsAsynchronously = runContinuationsAsynchronously;
}
[MethodImpl(MethodImplOptions.Synchronized)]
protected void Complete()
{
Interlocked.Exchange(ref continuation, null)?.Invoke();
}
[MethodImpl(MethodImplOptions.Synchronized)]
[System.Runtime.CompilerServices.NullableContext(1)]
public void OnCompleted(Action callback)
{
if (IsCompleted)
callback();
else
continuation = (Action)Delegate.Combine(continuation, runContinuationsAsynchronously ? Continuation.Create(callback) : callback);
}
}
}