From 0e6a5a3caacf324ad74dc76cc96f11e134d1b293 Mon Sep 17 00:00:00 2001 From: neuecc Date: Mon, 26 Aug 2019 18:42:22 +0900 Subject: [PATCH] ReadMe --- README.md | 26 ++ .../ContinuationSentinel.cs | 250 ------------------ 2 files changed, 26 insertions(+), 250 deletions(-) diff --git a/README.md b/README.md index 7a1d3c5..06edf2d 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,34 @@ ValueTaskSupplement === [![CircleCI](https://circleci.com/gh/Cysharp/ValueTaskSupplement.svg?style=svg)](https://circleci.com/gh/Cysharp/ValueTaskSupplement) +Append supplemental methods(`WhenAny`, `WhenAll`, `Lazy`) to ValueTask. + > PM> Install-Package [ValueTaskSupplement](https://www.nuget.org/packages/ValueTaskSupplement) +How to Use +--- +```csharp +using ValueTaskSupplement; // namespace + +async ValueTask Demo() +{ + ValueTask task1 = LoadAsyncA(); + ValueTask task2 = LoadAsyncB(); + ValueTask task3 = LoadAsyncC(); + + // await ValueTasks with tuple + var (a, b, c) = await ValueTaskEx.WhenAll(task1, task2, task3); + + // WhenAny with int winIndex + var (winIndex, a, b, c) = await ValueTaskEx.WhenAny(task1, task2, task2); + + // Lazy(called factory once and delayed) but you can use same type(ValueTask) + ValueTask asyncLazy = ValueTaskEx.Lazy(async () => 9999); +} +``` + +All method is based on `IValueTaskSource` so fast and less allocation. + License --- This library is under the MIT License. diff --git a/src/ValueTaskSupplement/ContinuationSentinel.cs b/src/ValueTaskSupplement/ContinuationSentinel.cs index e054083..f456da0 100644 --- a/src/ValueTaskSupplement/ContinuationSentinel.cs +++ b/src/ValueTaskSupplement/ContinuationSentinel.cs @@ -1,9 +1,4 @@ using System; -using System.Runtime.CompilerServices; -using System.Runtime.ExceptionServices; -using System.Threading; -using System.Threading.Tasks; -using System.Threading.Tasks.Sources; namespace ValueTaskSupplement { @@ -12,249 +7,4 @@ internal static class ContinuationSentinel public static readonly Action AvailableContinuation = _ => { }; public static readonly Action CompletedContinuation = _ => { }; } - - //public static class ValueTaskEx - //{ - // public static ValueTask<(T0, T1, T2)> WhenAll(ValueTask t0, ValueTask t1, ValueTask t2) - // { - // if (t0.IsCompletedSuccessfully && t1.IsCompletedSuccessfully && t2.IsCompletedSuccessfully) - // { - // return new ValueTask<(T0, T1, T2)>((t0.Result, t1.Result, t2.Result)); - // } - - // return new ValueTask<(T0, T1, T2)>(new WhenAllPromise(t0, t1, t2), 0); - // } - - // class WhenAllPromise : IValueTaskSource<(T0, T1, T2)> - // { - // const int ResultCount = 3; - // static readonly ContextCallback execContextCallback = ExecutionContextCallback; - // static readonly SendOrPostCallback syncContextCallback = SynchronizationContextCallback; - - // T0 t0 = default(T0); - // T1 t1 = default(T1); - // T2 t2 = default(T2); - // int completedCount = 0; - // ExceptionDispatchInfo exception; - // ValueTaskAwaiter awaiter0; - // ValueTaskAwaiter awaiter1; - // ValueTaskAwaiter awaiter2; - - // Action continuation = ContinuationSentinel.AvailableContinuation; - // object state; - // SynchronizationContext syncContext; - // ExecutionContext execContext; - - // public WhenAllPromise(ValueTask task0, ValueTask task1, ValueTask task2) - // { - // { - // var awaiter = task0.GetAwaiter(); - // if (awaiter.IsCompleted) - // { - // try - // { - // t0 = awaiter.GetResult(); - // } - // catch (Exception ex) - // { - // exception = ExceptionDispatchInfo.Capture(ex); - // return; - // } - // TryInvokeContinuationWithIncrement(); - // } - // else - // { - // awaiter0 = awaiter; - // awaiter.UnsafeOnCompleted(ContinuationT0); - // } - // } - // { - // var awaiter = task1.GetAwaiter(); - // if (awaiter.IsCompleted) - // { - // try - // { - // t1 = awaiter.GetResult(); - // } - // catch (Exception ex) - // { - // exception = ExceptionDispatchInfo.Capture(ex); - // return; - // } - // TryInvokeContinuationWithIncrement(); - // } - // else - // { - // awaiter1 = awaiter; - // awaiter.UnsafeOnCompleted(ContinuationT1); - // } - // } - // { - // var awaiter = task2.GetAwaiter(); - // if (awaiter.IsCompleted) - // { - // try - // { - // t2 = awaiter.GetResult(); - // } - // catch (Exception ex) - // { - // exception = ExceptionDispatchInfo.Capture(ex); - // return; - // } - // TryInvokeContinuationWithIncrement(); - // } - // else - // { - // awaiter2 = awaiter; - // awaiter.UnsafeOnCompleted(ContinuationT2); - // } - // } - // } - - // void ContinuationT0() - // { - // try - // { - // t0 = awaiter0.GetResult(); - // } - // catch (Exception ex) - // { - // exception = ExceptionDispatchInfo.Capture(ex); - // TryInvokeContinuation(); - // return; - // } - // TryInvokeContinuationWithIncrement(); - // } - - // void ContinuationT1() - // { - // try - // { - // t1 = awaiter1.GetResult(); - // } - // catch (Exception ex) - // { - // exception = ExceptionDispatchInfo.Capture(ex); - // TryInvokeContinuation(); - // return; - // } - // TryInvokeContinuationWithIncrement(); - // } - - // void ContinuationT2() - // { - // try - // { - // t2 = awaiter2.GetResult(); - // } - // catch (Exception ex) - // { - // exception = ExceptionDispatchInfo.Capture(ex); - // TryInvokeContinuation(); - // return; - // } - // TryInvokeContinuationWithIncrement(); - // } - - // void TryInvokeContinuationWithIncrement() - // { - // if (Interlocked.Increment(ref completedCount) == ResultCount) - // { - // TryInvokeContinuation(); - // } - // } - - // void TryInvokeContinuation() - // { - // var c = Interlocked.Exchange(ref continuation, ContinuationSentinel.CompletedContinuation); - // if (c != ContinuationSentinel.AvailableContinuation && c != ContinuationSentinel.CompletedContinuation) - // { - // var spinWait = new SpinWait(); - // while (state == null) // worst case, state is not set yet so wait. - // { - // spinWait.SpinOnce(); - // } - - // if (execContext != null) - // { - // ExecutionContext.Run(execContext, execContextCallback, Tuple.Create(c, this)); - // } - // else if (syncContext != null) - // { - // syncContext.Post(syncContextCallback, Tuple.Create(c, this)); - // } - // else - // { - // c(state); - // } - // } - // } - - // public (T0, T1, T2) GetResult(short token) - // { - // if (exception != null) - // { - // exception.Throw(); - // } - // return (t0, t1, t2); - // } - - // public ValueTaskSourceStatus GetStatus(short token) - // { - // return (completedCount == ResultCount) ? ValueTaskSourceStatus.Succeeded - // : (exception != null) ? ((exception.SourceException is OperationCanceledException) ? ValueTaskSourceStatus.Canceled : ValueTaskSourceStatus.Faulted) - // : ValueTaskSourceStatus.Pending; - // } - - // public void OnCompleted(Action continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags) - // { - // if (Interlocked.CompareExchange(ref this.continuation, continuation, ContinuationSentinel.AvailableContinuation) != ContinuationSentinel.AvailableContinuation) - // { - // throw new InvalidOperationException("does not allow multiple await."); - // } - - // this.state = state; - // if ((flags & ValueTaskSourceOnCompletedFlags.FlowExecutionContext) == ValueTaskSourceOnCompletedFlags.FlowExecutionContext) - // { - // execContext = ExecutionContext.Capture(); - // } - // if ((flags & ValueTaskSourceOnCompletedFlags.UseSchedulingContext) == ValueTaskSourceOnCompletedFlags.UseSchedulingContext) - // { - // syncContext = SynchronizationContext.Current; - // } - - // if (GetStatus(token) != ValueTaskSourceStatus.Pending) - // { - // TryInvokeContinuation(); - // } - // } - - // static void ExecutionContextCallback(object state) - // { - // var t = (Tuple, WhenAllPromise>)state; - // var self = t.Item2; - // if (self.syncContext != null) - // { - // SynchronizationContextCallback(state); - // } - // else - // { - // var invokeState = self.state; - // self.state = null; - // t.Item1.Invoke(invokeState); - // } - // } - - // static void SynchronizationContextCallback(object state) - // { - // var t = (Tuple, WhenAllPromise>)state; - // var self = t.Item2; - // var invokeState = self.state; - // self.state = null; - // t.Item1.Invoke(invokeState); - // } - // } - - //} }