#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member 
 | 
  
 | 
using System; 
 | 
using System.Collections.Generic; 
 | 
using System.Threading; 
 | 
using Cysharp.Threading.Tasks.Internal; 
 | 
  
 | 
namespace Cysharp.Threading.Tasks 
 | 
{ 
 | 
    public partial struct UniTask 
 | 
    { 
 | 
        public static UniTask<T[]> WhenAll<T>(params UniTask<T>[] tasks) 
 | 
        { 
 | 
            if (tasks.Length == 0) 
 | 
            { 
 | 
                return UniTask.FromResult(Array.Empty<T>()); 
 | 
            } 
 | 
  
 | 
            return new UniTask<T[]>(new WhenAllPromise<T>(tasks, tasks.Length), 0); 
 | 
        } 
 | 
  
 | 
        public static UniTask<T[]> WhenAll<T>(IEnumerable<UniTask<T>> tasks) 
 | 
        { 
 | 
            using (var span = ArrayPoolUtil.Materialize(tasks)) 
 | 
            { 
 | 
                var promise = new WhenAllPromise<T>(span.Array, span.Length); // consumed array in constructor. 
 | 
                return new UniTask<T[]>(promise, 0); 
 | 
            } 
 | 
        } 
 | 
  
 | 
        public static UniTask WhenAll(params UniTask[] tasks) 
 | 
        { 
 | 
            if (tasks.Length == 0) 
 | 
            { 
 | 
                return UniTask.CompletedTask; 
 | 
            } 
 | 
  
 | 
            return new UniTask(new WhenAllPromise(tasks, tasks.Length), 0); 
 | 
        } 
 | 
  
 | 
        public static UniTask WhenAll(IEnumerable<UniTask> tasks) 
 | 
        { 
 | 
            using (var span = ArrayPoolUtil.Materialize(tasks)) 
 | 
            { 
 | 
                var promise = new WhenAllPromise(span.Array, span.Length); // consumed array in constructor. 
 | 
                return new UniTask(promise, 0); 
 | 
            } 
 | 
        } 
 | 
  
 | 
        sealed class WhenAllPromise<T> : IUniTaskSource<T[]> 
 | 
        { 
 | 
            T[] result; 
 | 
            int completeCount; 
 | 
            UniTaskCompletionSourceCore<T[]> core; // don't reset(called after GetResult, will invoke TrySetException.) 
 | 
  
 | 
            public WhenAllPromise(UniTask<T>[] tasks, int tasksLength) 
 | 
            { 
 | 
                TaskTracker.TrackActiveTask(this, 3); 
 | 
  
 | 
                this.completeCount = 0; 
 | 
  
 | 
                if (tasksLength == 0) 
 | 
                { 
 | 
                    this.result = Array.Empty<T>(); 
 | 
                    core.TrySetResult(result); 
 | 
                    return; 
 | 
                } 
 | 
  
 | 
                this.result = new T[tasksLength]; 
 | 
  
 | 
                for (int i = 0; i < tasksLength; i++) 
 | 
                { 
 | 
                    UniTask<T>.Awaiter awaiter; 
 | 
                    try 
 | 
                    { 
 | 
                        awaiter = tasks[i].GetAwaiter(); 
 | 
                    } 
 | 
                    catch (Exception ex) 
 | 
                    { 
 | 
                        core.TrySetException(ex); 
 | 
                        continue; 
 | 
                    } 
 | 
  
 | 
                    if (awaiter.IsCompleted) 
 | 
                    { 
 | 
                        TryInvokeContinuation(this, awaiter, i); 
 | 
                    } 
 | 
                    else 
 | 
                    { 
 | 
                        awaiter.SourceOnCompleted(state => 
 | 
                        { 
 | 
                            using (var t = (StateTuple<WhenAllPromise<T>, UniTask<T>.Awaiter, int>)state) 
 | 
                            { 
 | 
                                TryInvokeContinuation(t.Item1, t.Item2, t.Item3); 
 | 
                            } 
 | 
                        }, StateTuple.Create(this, awaiter, i)); 
 | 
                    } 
 | 
                } 
 | 
            } 
 | 
  
 | 
            static void TryInvokeContinuation(WhenAllPromise<T> self, in UniTask<T>.Awaiter awaiter, int i) 
 | 
            { 
 | 
                try 
 | 
                { 
 | 
                    self.result[i] = awaiter.GetResult(); 
 | 
                } 
 | 
                catch (Exception ex) 
 | 
                { 
 | 
                    self.core.TrySetException(ex); 
 | 
                    return; 
 | 
                } 
 | 
  
 | 
                if (Interlocked.Increment(ref self.completeCount) == self.result.Length) 
 | 
                { 
 | 
                    self.core.TrySetResult(self.result); 
 | 
                } 
 | 
            } 
 | 
  
 | 
            public T[] GetResult(short token) 
 | 
            { 
 | 
                TaskTracker.RemoveTracking(this); 
 | 
                GC.SuppressFinalize(this); 
 | 
                return core.GetResult(token); 
 | 
            } 
 | 
  
 | 
            void IUniTaskSource.GetResult(short token) 
 | 
            { 
 | 
                GetResult(token); 
 | 
            } 
 | 
  
 | 
            public UniTaskStatus GetStatus(short token) 
 | 
            { 
 | 
                return core.GetStatus(token); 
 | 
            } 
 | 
  
 | 
            public UniTaskStatus UnsafeGetStatus() 
 | 
            { 
 | 
                return core.UnsafeGetStatus(); 
 | 
            } 
 | 
  
 | 
            public void OnCompleted(Action<object> continuation, object state, short token) 
 | 
            { 
 | 
                core.OnCompleted(continuation, state, token); 
 | 
            } 
 | 
        } 
 | 
  
 | 
        sealed class WhenAllPromise : IUniTaskSource 
 | 
        { 
 | 
            int completeCount; 
 | 
            int tasksLength; 
 | 
            UniTaskCompletionSourceCore<AsyncUnit> core; // don't reset(called after GetResult, will invoke TrySetException.) 
 | 
  
 | 
            public WhenAllPromise(UniTask[] tasks, int tasksLength) 
 | 
            { 
 | 
                TaskTracker.TrackActiveTask(this, 3); 
 | 
  
 | 
                this.tasksLength = tasksLength; 
 | 
                this.completeCount = 0; 
 | 
  
 | 
                if (tasksLength == 0) 
 | 
                { 
 | 
                    core.TrySetResult(AsyncUnit.Default); 
 | 
                    return; 
 | 
                } 
 | 
  
 | 
                for (int i = 0; i < tasksLength; i++) 
 | 
                { 
 | 
                    UniTask.Awaiter awaiter; 
 | 
                    try 
 | 
                    { 
 | 
                        awaiter = tasks[i].GetAwaiter(); 
 | 
                    } 
 | 
                    catch (Exception ex) 
 | 
                    { 
 | 
                        core.TrySetException(ex); 
 | 
                        continue; 
 | 
                    } 
 | 
  
 | 
                    if (awaiter.IsCompleted) 
 | 
                    { 
 | 
                        TryInvokeContinuation(this, awaiter); 
 | 
                    } 
 | 
                    else 
 | 
                    { 
 | 
                        awaiter.SourceOnCompleted(state => 
 | 
                        { 
 | 
                            using (var t = (StateTuple<WhenAllPromise, UniTask.Awaiter>)state) 
 | 
                            { 
 | 
                                TryInvokeContinuation(t.Item1, t.Item2); 
 | 
                            } 
 | 
                        }, StateTuple.Create(this, awaiter)); 
 | 
                    } 
 | 
                } 
 | 
            } 
 | 
  
 | 
            static void TryInvokeContinuation(WhenAllPromise self, in UniTask.Awaiter awaiter) 
 | 
            { 
 | 
                try 
 | 
                { 
 | 
                    awaiter.GetResult(); 
 | 
                } 
 | 
                catch (Exception ex) 
 | 
                { 
 | 
                    self.core.TrySetException(ex); 
 | 
                    return; 
 | 
                } 
 | 
  
 | 
                if (Interlocked.Increment(ref self.completeCount) == self.tasksLength) 
 | 
                { 
 | 
                    self.core.TrySetResult(AsyncUnit.Default); 
 | 
                } 
 | 
            } 
 | 
  
 | 
            public void GetResult(short token) 
 | 
            { 
 | 
                TaskTracker.RemoveTracking(this); 
 | 
                GC.SuppressFinalize(this); 
 | 
                core.GetResult(token); 
 | 
            } 
 | 
  
 | 
            public UniTaskStatus GetStatus(short token) 
 | 
            { 
 | 
                return core.GetStatus(token); 
 | 
            } 
 | 
  
 | 
            public UniTaskStatus UnsafeGetStatus() 
 | 
            { 
 | 
                return core.UnsafeGetStatus(); 
 | 
            } 
 | 
  
 | 
            public void OnCompleted(Action<object> continuation, object state, short token) 
 | 
            { 
 | 
                core.OnCompleted(continuation, state, token); 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
} 
 |