DotNext.Threading by .NET Foundation and Contributors

<PackageReference Include="DotNext.Threading" Version="5.5.0" />

 ValueTaskCompletionSource<T>

Represents the producer side of ValueTask<T>.
using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using System.Threading.Tasks.Sources; namespace DotNext.Threading.Tasks { [NullableContext(1)] [Nullable(0)] public class ValueTaskCompletionSource<[Nullable(2)] T> : ManualResetCompletionSource, IValueTaskSource<T>, IValueTaskSource { private sealed class LinkedTaskCompletionSource : TaskCompletionSource<T> { private IValueTaskSource<T> source; private short version; internal LinkedTaskCompletionSource(object state) : base(state, TaskCreationOptions.None) { } internal void LinkTo(IValueTaskSource<T> source, short version) { this.source = source; this.version = version; source.OnCompleted(delegate(object state) { Unsafe.As<LinkedTaskCompletionSource>(state).OnCompleted(); }, this, version, ValueTaskSourceOnCompletedFlags.None); } private void OnCompleted() { if (source != null) try { TrySetResult(source.GetResult(version)); } catch (OperationCanceledException ex) { TrySetCanceled(ex.CancellationToken); } catch (Exception exception) { TrySetException(exception); } source = null; } } private Result<T> result; public ValueTaskCompletionSource(bool runContinuationsAsynchronously = true) : base(runContinuationsAsynchronously) { } private static Result<T> FromCanceled(CancellationToken token) { return new Result<T>((Exception)new OperationCanceledException(token)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TrySetResult(T value) { return TrySetResult(null, value); } public unsafe bool TrySetResult([Nullable(2)] object completionData, T value) { return SetResult(completionData, null, (IntPtr)(void*), value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TrySetResult(short completionToken, T value) { return TrySetResult(null, completionToken, value); } public unsafe bool TrySetResult([Nullable(2)] object completionData, short completionToken, T value) { return SetResult(completionData, completionToken, (IntPtr)(void*), value); } public unsafe sealed override bool TrySetException([Nullable(2)] object completionData, Exception e) { return SetResult(completionData, null, (IntPtr)(void*), e); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TrySetException(short completionToken, Exception e) { return TrySetException(null, completionToken, e); } public unsafe bool TrySetException([Nullable(2)] object completionData, short completionToken, Exception e) { return SetResult(completionData, completionToken, (IntPtr)(void*), e); } [NullableContext(2)] public unsafe sealed override bool TrySetCanceled(object completionData, CancellationToken token) { return SetResult(completionData, null, (IntPtr)(void*), token); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TrySetCanceled(short completionToken, CancellationToken token) { return TrySetCanceled(null, completionToken, token); } [NullableContext(2)] public unsafe bool TrySetCanceled(object completionData, short completionToken, CancellationToken token) { return SetResult(completionData, completionToken, (IntPtr)(void*), token); } private protected sealed override bool CompleteAsTimedOut() { Result<T> val = OnTimeout(); return SetResult(ref val, null); } private protected sealed override bool CompleteAsCanceled(CancellationToken token) { Result<T> val = OnCanceled(token); return SetResult(ref val, null); } private bool SetResult<TArg>(object completionData, short? completionToken, IntPtr func, TArg arg) { EnterLock(); bool flag = default(bool); try { flag = versionAndStatus.CanBeCompleted(completionToken); if (!flag) return flag; Result<T> val = ; if (!this.SetResult(ref val, completionData)) return flag; } finally { ExitLock(); } Resume(); return flag; } private bool SetResult([In] [IsReadOnly] ref Result<T> result, object completionData = null) { this.result = result; return SetResult(completionData); } internal bool TrySetResult(object completionData, short? completionToken, [In] [IsReadOnly] ref Result<T> result, out bool resumable) { EnterLock(); try { bool flag; resumable = ((flag = versionAndStatus.CanBeCompleted(completionToken)) && SetResult(ref result, completionData)); return flag; } finally { ExitLock(); } } protected override void Cleanup() { result = default(Result<T>); } [return: Nullable(new byte[] { 0, 1 })] protected virtual Result<T> OnTimeout() { return new Result<T>((Exception)new TimeoutException()); } [return: Nullable(new byte[] { 0, 1 })] protected virtual Result<T> OnCanceled(CancellationToken token) { return new Result<T>((Exception)new OperationCanceledException(token)); } [return: Nullable(new byte[] { 0, 1 })] public ValueTask<T> CreateTask(TimeSpan timeout, CancellationToken token) { short? nullable = Activate(timeout, token); if (!nullable.HasValue) throw new InvalidOperationException(ExceptionMessages.InvalidSourceState); short valueOrDefault = nullable.GetValueOrDefault(); return new ValueTask<T>(this, valueOrDefault); } ValueTask<T> Invoke(TimeSpan timeout, CancellationToken token) { return CreateTask(timeout, token); } ValueTask Invoke(TimeSpan timeout, CancellationToken token) { short? nullable = Activate(timeout, token); if (!nullable.HasValue) throw new InvalidOperationException(ExceptionMessages.InvalidSourceState); short valueOrDefault = nullable.GetValueOrDefault(); return new ValueTask(this, valueOrDefault); } private T GetResult(short token) { Result<T> val = result; versionAndStatus.Consume(token); AfterConsumed(); return val.get_Value(); } T IValueTaskSource<T>.GetResult(short token) { return GetResult(token); } void IValueTaskSource.GetResult(short token) { GetResult(token); } private ValueTaskSourceStatus GetStatus(short token) { Exception error = result.get_Error(); VersionAndStatus versionAndStatus = base.versionAndStatus.VolatileRead(); if (token != versionAndStatus.Version) throw new InvalidOperationException(ExceptionMessages.InvalidSourceToken); if (versionAndStatus.IsCompleted) return (error == null) ? ValueTaskSourceStatus.Succeeded : ((!(error is OperationCanceledException)) ? ValueTaskSourceStatus.Faulted : ValueTaskSourceStatus.Canceled); return ValueTaskSourceStatus.Pending; } ValueTaskSourceStatus IValueTaskSource<T>.GetStatus(short token) { return GetStatus(token); } ValueTaskSourceStatus IValueTaskSource.GetStatus(short token) { return GetStatus(token); } void IValueTaskSource<T>.OnCompleted(Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags) { OnCompleted(continuation, state, token, flags); } void IValueTaskSource.OnCompleted(Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags) { OnCompleted(continuation, state, token, flags); } public TaskCompletionSource<T> CreateLinkedTaskCompletionSource([Nullable(2)] object userData, TimeSpan timeout, CancellationToken token) { short? nullable = Activate(timeout, token); if (!nullable.HasValue) throw new InvalidOperationException(ExceptionMessages.InvalidSourceState); short valueOrDefault = nullable.GetValueOrDefault(); LinkedTaskCompletionSource linkedTaskCompletionSource = new LinkedTaskCompletionSource(userData); linkedTaskCompletionSource.LinkTo(this, valueOrDefault); return linkedTaskCompletionSource; } } }