Skip to content

Commit

Permalink
Add WhenAll extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
neuecc committed Aug 26, 2019
1 parent 98bfdef commit 0403247
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 0 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,16 @@ public static ValueTask<(T0, T1)> WhenAll<T0, T1>(ValueTask<T0> task0, ValueTask
public static ValueTask<(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15)> WhenAll<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>(ValueTask<T0> task0, ValueTask<T1> task1, ValueTask<T2> task2, ValueTask<T3> task3, ValueTask<T4> task4, ValueTask<T5> task5, ValueTask<T6> task6, ValueTask<T7> task7, ValueTask<T8> task8, ValueTask<T9> task9, ValueTask<T10> task10, ValueTask<T11> task11, ValueTask<T12> task12, ValueTask<T13> task13, ValueTask<T14> task14, ValueTask<T15> task15)
```

`IEnumerable<ValueTask<T>>` and `(ValueTask<T0>, ValueTask<T1>, ...)` can await directly.

```csharp
using ValueTaskSupplement;

// same as ValueTaskEx.WhenAll(new []{ }), ValueTaskEx.WhenAll(A, B, C)
var result = await new[] { LoadAsyncA(), LoadAsyncB(), LoadAsyncC() };
var (x, y, z) = await (LoadAsyncA(), LoadAsyncB(), LoadAsyncC());
```

WhenAny
---

Expand Down
5 changes: 5 additions & 0 deletions src/ValueTaskSupplement/ValueTaskEx.WhenAll_Array.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ public static ValueTask<T[]> WhenAll<T>(IEnumerable<ValueTask<T>> tasks)
return new ValueTask<T[]>(new WhenAllPromiseAll<T>(tasks), 0);
}

public static ValueTaskAwaiter<T[]> GetAwaiter<T>(this IEnumerable<ValueTask<T>> tasks)
{
return WhenAll(tasks).GetAwaiter();
}

class WhenAllPromiseAll<T> : IValueTaskSource<T[]>
{
static readonly ContextCallback execContextCallback = ExecutionContextCallback;
Expand Down
9 changes: 9 additions & 0 deletions src/ValueTaskSupplement/ValueTaskSupplement.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>ValueTaskEx.WhenAny.cs</LastGenOutput>
</None>
<None Update="ValueTaskWhenAllExtensions.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>ValueTaskWhenAllExtensions.cs</LastGenOutput>
</None>
</ItemGroup>

<ItemGroup>
Expand All @@ -48,6 +52,11 @@
<AutoGen>True</AutoGen>
<DependentUpon>ValueTaskEx.WhenAny.tt</DependentUpon>
</Compile>
<Compile Update="ValueTaskWhenAllExtensions.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>ValueTaskWhenAllExtensions.tt</DependentUpon>
</Compile>
</ItemGroup>

</Project>
84 changes: 84 additions & 0 deletions src/ValueTaskSupplement/ValueTaskWhenAllExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
using System.Threading.Tasks;
using System.Runtime.CompilerServices;

namespace ValueTaskSupplement
{
public static class ValueTaskWhenAllExtensions
{

public static ValueTaskAwaiter<(T0, T1)> GetAwaiter<T0, T1>(this (ValueTask<T0> task0, ValueTask<T1> task1) tasks)
{
return ValueTaskEx.WhenAll(tasks.Item1, tasks.Item2).GetAwaiter();
}

public static ValueTaskAwaiter<(T0, T1, T2)> GetAwaiter<T0, T1, T2>(this (ValueTask<T0> task0, ValueTask<T1> task1, ValueTask<T2> task2) tasks)
{
return ValueTaskEx.WhenAll(tasks.Item1, tasks.Item2, tasks.Item3).GetAwaiter();
}

public static ValueTaskAwaiter<(T0, T1, T2, T3)> GetAwaiter<T0, T1, T2, T3>(this (ValueTask<T0> task0, ValueTask<T1> task1, ValueTask<T2> task2, ValueTask<T3> task3) tasks)
{
return ValueTaskEx.WhenAll(tasks.Item1, tasks.Item2, tasks.Item3, tasks.Item4).GetAwaiter();
}

public static ValueTaskAwaiter<(T0, T1, T2, T3, T4)> GetAwaiter<T0, T1, T2, T3, T4>(this (ValueTask<T0> task0, ValueTask<T1> task1, ValueTask<T2> task2, ValueTask<T3> task3, ValueTask<T4> task4) tasks)
{
return ValueTaskEx.WhenAll(tasks.Item1, tasks.Item2, tasks.Item3, tasks.Item4, tasks.Item5).GetAwaiter();
}

public static ValueTaskAwaiter<(T0, T1, T2, T3, T4, T5)> GetAwaiter<T0, T1, T2, T3, T4, T5>(this (ValueTask<T0> task0, ValueTask<T1> task1, ValueTask<T2> task2, ValueTask<T3> task3, ValueTask<T4> task4, ValueTask<T5> task5) tasks)
{
return ValueTaskEx.WhenAll(tasks.Item1, tasks.Item2, tasks.Item3, tasks.Item4, tasks.Item5, tasks.Item6).GetAwaiter();
}

public static ValueTaskAwaiter<(T0, T1, T2, T3, T4, T5, T6)> GetAwaiter<T0, T1, T2, T3, T4, T5, T6>(this (ValueTask<T0> task0, ValueTask<T1> task1, ValueTask<T2> task2, ValueTask<T3> task3, ValueTask<T4> task4, ValueTask<T5> task5, ValueTask<T6> task6) tasks)
{
return ValueTaskEx.WhenAll(tasks.Item1, tasks.Item2, tasks.Item3, tasks.Item4, tasks.Item5, tasks.Item6, tasks.Item7).GetAwaiter();
}

public static ValueTaskAwaiter<(T0, T1, T2, T3, T4, T5, T6, T7)> GetAwaiter<T0, T1, T2, T3, T4, T5, T6, T7>(this (ValueTask<T0> task0, ValueTask<T1> task1, ValueTask<T2> task2, ValueTask<T3> task3, ValueTask<T4> task4, ValueTask<T5> task5, ValueTask<T6> task6, ValueTask<T7> task7) tasks)
{
return ValueTaskEx.WhenAll(tasks.Item1, tasks.Item2, tasks.Item3, tasks.Item4, tasks.Item5, tasks.Item6, tasks.Item7, tasks.Item8).GetAwaiter();
}

public static ValueTaskAwaiter<(T0, T1, T2, T3, T4, T5, T6, T7, T8)> GetAwaiter<T0, T1, T2, T3, T4, T5, T6, T7, T8>(this (ValueTask<T0> task0, ValueTask<T1> task1, ValueTask<T2> task2, ValueTask<T3> task3, ValueTask<T4> task4, ValueTask<T5> task5, ValueTask<T6> task6, ValueTask<T7> task7, ValueTask<T8> task8) tasks)
{
return ValueTaskEx.WhenAll(tasks.Item1, tasks.Item2, tasks.Item3, tasks.Item4, tasks.Item5, tasks.Item6, tasks.Item7, tasks.Item8, tasks.Item9).GetAwaiter();
}

public static ValueTaskAwaiter<(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9)> GetAwaiter<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>(this (ValueTask<T0> task0, ValueTask<T1> task1, ValueTask<T2> task2, ValueTask<T3> task3, ValueTask<T4> task4, ValueTask<T5> task5, ValueTask<T6> task6, ValueTask<T7> task7, ValueTask<T8> task8, ValueTask<T9> task9) tasks)
{
return ValueTaskEx.WhenAll(tasks.Item1, tasks.Item2, tasks.Item3, tasks.Item4, tasks.Item5, tasks.Item6, tasks.Item7, tasks.Item8, tasks.Item9, tasks.Item10).GetAwaiter();
}

public static ValueTaskAwaiter<(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)> GetAwaiter<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(this (ValueTask<T0> task0, ValueTask<T1> task1, ValueTask<T2> task2, ValueTask<T3> task3, ValueTask<T4> task4, ValueTask<T5> task5, ValueTask<T6> task6, ValueTask<T7> task7, ValueTask<T8> task8, ValueTask<T9> task9, ValueTask<T10> task10) tasks)
{
return ValueTaskEx.WhenAll(tasks.Item1, tasks.Item2, tasks.Item3, tasks.Item4, tasks.Item5, tasks.Item6, tasks.Item7, tasks.Item8, tasks.Item9, tasks.Item10, tasks.Item11).GetAwaiter();
}

public static ValueTaskAwaiter<(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11)> GetAwaiter<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>(this (ValueTask<T0> task0, ValueTask<T1> task1, ValueTask<T2> task2, ValueTask<T3> task3, ValueTask<T4> task4, ValueTask<T5> task5, ValueTask<T6> task6, ValueTask<T7> task7, ValueTask<T8> task8, ValueTask<T9> task9, ValueTask<T10> task10, ValueTask<T11> task11) tasks)
{
return ValueTaskEx.WhenAll(tasks.Item1, tasks.Item2, tasks.Item3, tasks.Item4, tasks.Item5, tasks.Item6, tasks.Item7, tasks.Item8, tasks.Item9, tasks.Item10, tasks.Item11, tasks.Item12).GetAwaiter();
}

public static ValueTaskAwaiter<(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12)> GetAwaiter<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>(this (ValueTask<T0> task0, ValueTask<T1> task1, ValueTask<T2> task2, ValueTask<T3> task3, ValueTask<T4> task4, ValueTask<T5> task5, ValueTask<T6> task6, ValueTask<T7> task7, ValueTask<T8> task8, ValueTask<T9> task9, ValueTask<T10> task10, ValueTask<T11> task11, ValueTask<T12> task12) tasks)
{
return ValueTaskEx.WhenAll(tasks.Item1, tasks.Item2, tasks.Item3, tasks.Item4, tasks.Item5, tasks.Item6, tasks.Item7, tasks.Item8, tasks.Item9, tasks.Item10, tasks.Item11, tasks.Item12, tasks.Item13).GetAwaiter();
}

public static ValueTaskAwaiter<(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13)> GetAwaiter<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>(this (ValueTask<T0> task0, ValueTask<T1> task1, ValueTask<T2> task2, ValueTask<T3> task3, ValueTask<T4> task4, ValueTask<T5> task5, ValueTask<T6> task6, ValueTask<T7> task7, ValueTask<T8> task8, ValueTask<T9> task9, ValueTask<T10> task10, ValueTask<T11> task11, ValueTask<T12> task12, ValueTask<T13> task13) tasks)
{
return ValueTaskEx.WhenAll(tasks.Item1, tasks.Item2, tasks.Item3, tasks.Item4, tasks.Item5, tasks.Item6, tasks.Item7, tasks.Item8, tasks.Item9, tasks.Item10, tasks.Item11, tasks.Item12, tasks.Item13, tasks.Item14).GetAwaiter();
}

public static ValueTaskAwaiter<(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14)> GetAwaiter<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>(this (ValueTask<T0> task0, ValueTask<T1> task1, ValueTask<T2> task2, ValueTask<T3> task3, ValueTask<T4> task4, ValueTask<T5> task5, ValueTask<T6> task6, ValueTask<T7> task7, ValueTask<T8> task8, ValueTask<T9> task9, ValueTask<T10> task10, ValueTask<T11> task11, ValueTask<T12> task12, ValueTask<T13> task13, ValueTask<T14> task14) tasks)
{
return ValueTaskEx.WhenAll(tasks.Item1, tasks.Item2, tasks.Item3, tasks.Item4, tasks.Item5, tasks.Item6, tasks.Item7, tasks.Item8, tasks.Item9, tasks.Item10, tasks.Item11, tasks.Item12, tasks.Item13, tasks.Item14, tasks.Item15).GetAwaiter();
}

public static ValueTaskAwaiter<(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15)> GetAwaiter<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>(this (ValueTask<T0> task0, ValueTask<T1> task1, ValueTask<T2> task2, ValueTask<T3> task3, ValueTask<T4> task4, ValueTask<T5> task5, ValueTask<T6> task6, ValueTask<T7> task7, ValueTask<T8> task8, ValueTask<T9> task9, ValueTask<T10> task10, ValueTask<T11> task11, ValueTask<T12> task12, ValueTask<T13> task13, ValueTask<T14> task14, ValueTask<T15> task15) tasks)
{
return ValueTaskEx.WhenAll(tasks.Item1, tasks.Item2, tasks.Item3, tasks.Item4, tasks.Item5, tasks.Item6, tasks.Item7, tasks.Item8, tasks.Item9, tasks.Item10, tasks.Item11, tasks.Item12, tasks.Item13, tasks.Item14, tasks.Item15, tasks.Item16).GetAwaiter();
}
}
}
27 changes: 27 additions & 0 deletions src/ValueTaskSupplement/ValueTaskWhenAllExtensions.tt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
using System.Threading.Tasks;
using System.Runtime.CompilerServices;

namespace ValueTaskSupplement
{
public static class ValueTaskWhenAllExtensions
{
<# for(var i = 1; i <= 15; i++) {
var range = Enumerable.Range(0, i + 1);
var t = string.Join(", ", range.Select(x => "T" + x));
var args = string.Join(", ", range.Select(x => $"ValueTask<T{x}> task{x}"));
var itemx = string.Join(", ", range.Select(x => $"tasks.Item{x + 1}"));
#>

public static ValueTaskAwaiter<(<#= t #>)> GetAwaiter<<#= t #>>(this (<#= args #>) tasks)
{
return ValueTaskEx.WhenAll(<#= itemx #>).GetAwaiter();
}
<# }#>
}
}
13 changes: 13 additions & 0 deletions tests/ValueTaskSupplement.Tests/WhenAllTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,19 @@ public async Task Array()
result.Should().BeEquivalentTo(new[] { 1, 2, 3 });
}

[Fact]
public async Task Extension()
{
var result = await new[] { CreateAsync(1), CreateAsync(2), CreateAsync(3) };
result[0].Should().Be(1);
result[1].Should().Be(2);
result[2].Should().Be(3);

var (x, y) = await (CreateAsync(10), CreateAsync(99));
x.Should().Be(10);
y.Should().Be(99);
}

ValueTask<int> CreateSync(int i)
{
return new ValueTask<int>(i);
Expand Down

0 comments on commit 0403247

Please sign in to comment.