<#@ 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 UniRx.Async.Internal; namespace UniRx.Async { 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 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 => $"(bool hasResult, T{x} result{x})")); var tfield = string.Join(", ", range.Select(x => $"self.t{x}")); Func getResult = j => string.Join(", ", range.Select(x => (x == j) ? "(true, result)" : "(false, 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 #>) { TaskTracker2.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>, UniTask>.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>.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) { TaskTracker2.RemoveTracking(this); GC.SuppressFinalize(this); return core.GetResult(token); } public UniTaskStatus GetStatus(short token) { return core.GetStatus(token); } public void OnCompleted(Action continuation, object state, short token) { core.OnCompleted(continuation, state, token); } public UniTaskStatus UnsafeGetStatus() { return core.UnsafeGetStatus(); } void IUniTaskSource.GetResult(short token) { GetResult(token); } ~WhenAnyPromise() { core.Reset(); } } <# } #> } }