You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
117 lines
4.0 KiB
117 lines
4.0 KiB
<#@ 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" #> |
|
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member |
|
using System; |
|
using System.Runtime.CompilerServices; |
|
using System.Runtime.ExceptionServices; |
|
using System.Threading; |
|
using Cysharp.Threading.Tasks.Internal; |
|
|
|
namespace Cysharp.Threading.Tasks |
|
{ |
|
public partial struct UniTask |
|
{ |
|
<# for(var i = 2; i <= 15; i++ ) { |
|
var range = Enumerable.Range(1, i); |
|
var t = string.Join(", ", range.Select(x => "T" + x)); |
|
var args = string.Join(", ", range.Select(x => $"UniTask<T{x}> task{x}")); |
|
var targs = string.Join(", ", range.Select(x => $"task{x}")); |
|
var tresult = string.Join(", ", range.Select(x => $"task{x}.GetAwaiter().GetResult()")); |
|
var tBool = string.Join(", ", range.Select(x => $"T{x} result{x}")); |
|
var tfield = string.Join(", ", range.Select(x => $"self.t{x}")); |
|
Func<int, string> getResult = j => string.Join(", ", range.Select(x => (x == j) ? "result" : "default")); |
|
#> |
|
public static UniTask<(int winArgumentIndex, <#= tBool #>)> WhenAny<<#= t #>>(<#= args #>) |
|
{ |
|
return new UniTask<(int winArgumentIndex, <#= tBool #>)>(new WhenAnyPromise<<#= t #>>(<#= targs #>), 0); |
|
} |
|
|
|
sealed class WhenAnyPromise<<#= t #>> : IUniTaskSource<(int, <#= tBool #>)> |
|
{ |
|
int completedCount; |
|
UniTaskCompletionSourceCore<(int, <#= tBool #>)> core; |
|
|
|
public WhenAnyPromise(<#= args #>) |
|
{ |
|
TaskTracker.TrackActiveTask(this, 3); |
|
|
|
this.completedCount = 0; |
|
<# for(var j = 1; j <= i; j++) { #> |
|
{ |
|
var awaiter = task<#= j #>.GetAwaiter(); |
|
|
|
if (awaiter.IsCompleted) |
|
{ |
|
TryInvokeContinuationT<#= j #>(this, awaiter); |
|
} |
|
else |
|
{ |
|
awaiter.SourceOnCompleted(state => |
|
{ |
|
using (var t = (StateTuple<WhenAnyPromise<<#= t #>>, UniTask<T<#= j #>>.Awaiter>)state) |
|
{ |
|
TryInvokeContinuationT<#= j #>(t.Item1, t.Item2); |
|
} |
|
}, StateTuple.Create(this, awaiter)); |
|
} |
|
} |
|
<# } #> |
|
} |
|
|
|
<# for(var j = 1; j <= i; j++) { #> |
|
static void TryInvokeContinuationT<#= j #>(WhenAnyPromise<<#= t #>> self, in UniTask<T<#= j #>>.Awaiter awaiter) |
|
{ |
|
T<#= j #> result; |
|
try |
|
{ |
|
result = awaiter.GetResult(); |
|
} |
|
catch (Exception ex) |
|
{ |
|
self.core.TrySetException(ex); |
|
return; |
|
} |
|
|
|
if (Interlocked.Increment(ref self.completedCount) == 1) |
|
{ |
|
self.core.TrySetResult((<#= j - 1 #>, <#= getResult(j) #>)); |
|
} |
|
} |
|
|
|
<# } #> |
|
|
|
public (int, <#= tBool #>) GetResult(short token) |
|
{ |
|
TaskTracker.RemoveTracking(this); |
|
GC.SuppressFinalize(this); |
|
return core.GetResult(token); |
|
} |
|
|
|
public UniTaskStatus GetStatus(short token) |
|
{ |
|
return core.GetStatus(token); |
|
} |
|
|
|
public void OnCompleted(Action<object> continuation, object state, short token) |
|
{ |
|
core.OnCompleted(continuation, state, token); |
|
} |
|
|
|
public UniTaskStatus UnsafeGetStatus() |
|
{ |
|
return core.UnsafeGetStatus(); |
|
} |
|
|
|
void IUniTaskSource.GetResult(short token) |
|
{ |
|
GetResult(token); |
|
} |
|
} |
|
|
|
<# } #> |
|
} |
|
} |