You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
11372 lines
431 KiB
C#
11372 lines
431 KiB
C#
using Cysharp.Threading.Tasks.Internal;
|
|
using System;
|
|
using System.Threading;
|
|
|
|
namespace Cysharp.Threading.Tasks.Linq
|
|
{
|
|
public static partial class UniTaskAsyncEnumerable
|
|
{
|
|
public static IUniTaskAsyncEnumerable<TResult> CombineLatest<T1, T2, TResult>(this IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, Func<T1, T2, TResult> resultSelector)
|
|
{
|
|
Error.ThrowArgumentNullException(source1, nameof(source1));
|
|
Error.ThrowArgumentNullException(source2, nameof(source2));
|
|
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
|
|
|
|
return new CombineLatest<T1, T2, TResult>(source1, source2, resultSelector);
|
|
}
|
|
|
|
public static IUniTaskAsyncEnumerable<TResult> CombineLatest<T1, T2, T3, TResult>(this IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, Func<T1, T2, T3, TResult> resultSelector)
|
|
{
|
|
Error.ThrowArgumentNullException(source1, nameof(source1));
|
|
Error.ThrowArgumentNullException(source2, nameof(source2));
|
|
Error.ThrowArgumentNullException(source3, nameof(source3));
|
|
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
|
|
|
|
return new CombineLatest<T1, T2, T3, TResult>(source1, source2, source3, resultSelector);
|
|
}
|
|
|
|
public static IUniTaskAsyncEnumerable<TResult> CombineLatest<T1, T2, T3, T4, TResult>(this IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, Func<T1, T2, T3, T4, TResult> resultSelector)
|
|
{
|
|
Error.ThrowArgumentNullException(source1, nameof(source1));
|
|
Error.ThrowArgumentNullException(source2, nameof(source2));
|
|
Error.ThrowArgumentNullException(source3, nameof(source3));
|
|
Error.ThrowArgumentNullException(source4, nameof(source4));
|
|
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
|
|
|
|
return new CombineLatest<T1, T2, T3, T4, TResult>(source1, source2, source3, source4, resultSelector);
|
|
}
|
|
|
|
public static IUniTaskAsyncEnumerable<TResult> CombineLatest<T1, T2, T3, T4, T5, TResult>(this IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, Func<T1, T2, T3, T4, T5, TResult> resultSelector)
|
|
{
|
|
Error.ThrowArgumentNullException(source1, nameof(source1));
|
|
Error.ThrowArgumentNullException(source2, nameof(source2));
|
|
Error.ThrowArgumentNullException(source3, nameof(source3));
|
|
Error.ThrowArgumentNullException(source4, nameof(source4));
|
|
Error.ThrowArgumentNullException(source5, nameof(source5));
|
|
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
|
|
|
|
return new CombineLatest<T1, T2, T3, T4, T5, TResult>(source1, source2, source3, source4, source5, resultSelector);
|
|
}
|
|
|
|
public static IUniTaskAsyncEnumerable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, TResult>(this IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, Func<T1, T2, T3, T4, T5, T6, TResult> resultSelector)
|
|
{
|
|
Error.ThrowArgumentNullException(source1, nameof(source1));
|
|
Error.ThrowArgumentNullException(source2, nameof(source2));
|
|
Error.ThrowArgumentNullException(source3, nameof(source3));
|
|
Error.ThrowArgumentNullException(source4, nameof(source4));
|
|
Error.ThrowArgumentNullException(source5, nameof(source5));
|
|
Error.ThrowArgumentNullException(source6, nameof(source6));
|
|
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
|
|
|
|
return new CombineLatest<T1, T2, T3, T4, T5, T6, TResult>(source1, source2, source3, source4, source5, source6, resultSelector);
|
|
}
|
|
|
|
public static IUniTaskAsyncEnumerable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, T7, TResult>(this IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, IUniTaskAsyncEnumerable<T7> source7, Func<T1, T2, T3, T4, T5, T6, T7, TResult> resultSelector)
|
|
{
|
|
Error.ThrowArgumentNullException(source1, nameof(source1));
|
|
Error.ThrowArgumentNullException(source2, nameof(source2));
|
|
Error.ThrowArgumentNullException(source3, nameof(source3));
|
|
Error.ThrowArgumentNullException(source4, nameof(source4));
|
|
Error.ThrowArgumentNullException(source5, nameof(source5));
|
|
Error.ThrowArgumentNullException(source6, nameof(source6));
|
|
Error.ThrowArgumentNullException(source7, nameof(source7));
|
|
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
|
|
|
|
return new CombineLatest<T1, T2, T3, T4, T5, T6, T7, TResult>(source1, source2, source3, source4, source5, source6, source7, resultSelector);
|
|
}
|
|
|
|
public static IUniTaskAsyncEnumerable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, TResult>(this IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, IUniTaskAsyncEnumerable<T7> source7, IUniTaskAsyncEnumerable<T8> source8, Func<T1, T2, T3, T4, T5, T6, T7, T8, TResult> resultSelector)
|
|
{
|
|
Error.ThrowArgumentNullException(source1, nameof(source1));
|
|
Error.ThrowArgumentNullException(source2, nameof(source2));
|
|
Error.ThrowArgumentNullException(source3, nameof(source3));
|
|
Error.ThrowArgumentNullException(source4, nameof(source4));
|
|
Error.ThrowArgumentNullException(source5, nameof(source5));
|
|
Error.ThrowArgumentNullException(source6, nameof(source6));
|
|
Error.ThrowArgumentNullException(source7, nameof(source7));
|
|
Error.ThrowArgumentNullException(source8, nameof(source8));
|
|
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
|
|
|
|
return new CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, TResult>(source1, source2, source3, source4, source5, source6, source7, source8, resultSelector);
|
|
}
|
|
|
|
public static IUniTaskAsyncEnumerable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult>(this IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, IUniTaskAsyncEnumerable<T7> source7, IUniTaskAsyncEnumerable<T8> source8, IUniTaskAsyncEnumerable<T9> source9, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> resultSelector)
|
|
{
|
|
Error.ThrowArgumentNullException(source1, nameof(source1));
|
|
Error.ThrowArgumentNullException(source2, nameof(source2));
|
|
Error.ThrowArgumentNullException(source3, nameof(source3));
|
|
Error.ThrowArgumentNullException(source4, nameof(source4));
|
|
Error.ThrowArgumentNullException(source5, nameof(source5));
|
|
Error.ThrowArgumentNullException(source6, nameof(source6));
|
|
Error.ThrowArgumentNullException(source7, nameof(source7));
|
|
Error.ThrowArgumentNullException(source8, nameof(source8));
|
|
Error.ThrowArgumentNullException(source9, nameof(source9));
|
|
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
|
|
|
|
return new CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult>(source1, source2, source3, source4, source5, source6, source7, source8, source9, resultSelector);
|
|
}
|
|
|
|
public static IUniTaskAsyncEnumerable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult>(this IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, IUniTaskAsyncEnumerable<T7> source7, IUniTaskAsyncEnumerable<T8> source8, IUniTaskAsyncEnumerable<T9> source9, IUniTaskAsyncEnumerable<T10> source10, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> resultSelector)
|
|
{
|
|
Error.ThrowArgumentNullException(source1, nameof(source1));
|
|
Error.ThrowArgumentNullException(source2, nameof(source2));
|
|
Error.ThrowArgumentNullException(source3, nameof(source3));
|
|
Error.ThrowArgumentNullException(source4, nameof(source4));
|
|
Error.ThrowArgumentNullException(source5, nameof(source5));
|
|
Error.ThrowArgumentNullException(source6, nameof(source6));
|
|
Error.ThrowArgumentNullException(source7, nameof(source7));
|
|
Error.ThrowArgumentNullException(source8, nameof(source8));
|
|
Error.ThrowArgumentNullException(source9, nameof(source9));
|
|
Error.ThrowArgumentNullException(source10, nameof(source10));
|
|
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
|
|
|
|
return new CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult>(source1, source2, source3, source4, source5, source6, source7, source8, source9, source10, resultSelector);
|
|
}
|
|
|
|
public static IUniTaskAsyncEnumerable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult>(this IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, IUniTaskAsyncEnumerable<T7> source7, IUniTaskAsyncEnumerable<T8> source8, IUniTaskAsyncEnumerable<T9> source9, IUniTaskAsyncEnumerable<T10> source10, IUniTaskAsyncEnumerable<T11> source11, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult> resultSelector)
|
|
{
|
|
Error.ThrowArgumentNullException(source1, nameof(source1));
|
|
Error.ThrowArgumentNullException(source2, nameof(source2));
|
|
Error.ThrowArgumentNullException(source3, nameof(source3));
|
|
Error.ThrowArgumentNullException(source4, nameof(source4));
|
|
Error.ThrowArgumentNullException(source5, nameof(source5));
|
|
Error.ThrowArgumentNullException(source6, nameof(source6));
|
|
Error.ThrowArgumentNullException(source7, nameof(source7));
|
|
Error.ThrowArgumentNullException(source8, nameof(source8));
|
|
Error.ThrowArgumentNullException(source9, nameof(source9));
|
|
Error.ThrowArgumentNullException(source10, nameof(source10));
|
|
Error.ThrowArgumentNullException(source11, nameof(source11));
|
|
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
|
|
|
|
return new CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult>(source1, source2, source3, source4, source5, source6, source7, source8, source9, source10, source11, resultSelector);
|
|
}
|
|
|
|
public static IUniTaskAsyncEnumerable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult>(this IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, IUniTaskAsyncEnumerable<T7> source7, IUniTaskAsyncEnumerable<T8> source8, IUniTaskAsyncEnumerable<T9> source9, IUniTaskAsyncEnumerable<T10> source10, IUniTaskAsyncEnumerable<T11> source11, IUniTaskAsyncEnumerable<T12> source12, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult> resultSelector)
|
|
{
|
|
Error.ThrowArgumentNullException(source1, nameof(source1));
|
|
Error.ThrowArgumentNullException(source2, nameof(source2));
|
|
Error.ThrowArgumentNullException(source3, nameof(source3));
|
|
Error.ThrowArgumentNullException(source4, nameof(source4));
|
|
Error.ThrowArgumentNullException(source5, nameof(source5));
|
|
Error.ThrowArgumentNullException(source6, nameof(source6));
|
|
Error.ThrowArgumentNullException(source7, nameof(source7));
|
|
Error.ThrowArgumentNullException(source8, nameof(source8));
|
|
Error.ThrowArgumentNullException(source9, nameof(source9));
|
|
Error.ThrowArgumentNullException(source10, nameof(source10));
|
|
Error.ThrowArgumentNullException(source11, nameof(source11));
|
|
Error.ThrowArgumentNullException(source12, nameof(source12));
|
|
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
|
|
|
|
return new CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult>(source1, source2, source3, source4, source5, source6, source7, source8, source9, source10, source11, source12, resultSelector);
|
|
}
|
|
|
|
public static IUniTaskAsyncEnumerable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult>(this IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, IUniTaskAsyncEnumerable<T7> source7, IUniTaskAsyncEnumerable<T8> source8, IUniTaskAsyncEnumerable<T9> source9, IUniTaskAsyncEnumerable<T10> source10, IUniTaskAsyncEnumerable<T11> source11, IUniTaskAsyncEnumerable<T12> source12, IUniTaskAsyncEnumerable<T13> source13, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult> resultSelector)
|
|
{
|
|
Error.ThrowArgumentNullException(source1, nameof(source1));
|
|
Error.ThrowArgumentNullException(source2, nameof(source2));
|
|
Error.ThrowArgumentNullException(source3, nameof(source3));
|
|
Error.ThrowArgumentNullException(source4, nameof(source4));
|
|
Error.ThrowArgumentNullException(source5, nameof(source5));
|
|
Error.ThrowArgumentNullException(source6, nameof(source6));
|
|
Error.ThrowArgumentNullException(source7, nameof(source7));
|
|
Error.ThrowArgumentNullException(source8, nameof(source8));
|
|
Error.ThrowArgumentNullException(source9, nameof(source9));
|
|
Error.ThrowArgumentNullException(source10, nameof(source10));
|
|
Error.ThrowArgumentNullException(source11, nameof(source11));
|
|
Error.ThrowArgumentNullException(source12, nameof(source12));
|
|
Error.ThrowArgumentNullException(source13, nameof(source13));
|
|
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
|
|
|
|
return new CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult>(source1, source2, source3, source4, source5, source6, source7, source8, source9, source10, source11, source12, source13, resultSelector);
|
|
}
|
|
|
|
public static IUniTaskAsyncEnumerable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult>(this IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, IUniTaskAsyncEnumerable<T7> source7, IUniTaskAsyncEnumerable<T8> source8, IUniTaskAsyncEnumerable<T9> source9, IUniTaskAsyncEnumerable<T10> source10, IUniTaskAsyncEnumerable<T11> source11, IUniTaskAsyncEnumerable<T12> source12, IUniTaskAsyncEnumerable<T13> source13, IUniTaskAsyncEnumerable<T14> source14, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult> resultSelector)
|
|
{
|
|
Error.ThrowArgumentNullException(source1, nameof(source1));
|
|
Error.ThrowArgumentNullException(source2, nameof(source2));
|
|
Error.ThrowArgumentNullException(source3, nameof(source3));
|
|
Error.ThrowArgumentNullException(source4, nameof(source4));
|
|
Error.ThrowArgumentNullException(source5, nameof(source5));
|
|
Error.ThrowArgumentNullException(source6, nameof(source6));
|
|
Error.ThrowArgumentNullException(source7, nameof(source7));
|
|
Error.ThrowArgumentNullException(source8, nameof(source8));
|
|
Error.ThrowArgumentNullException(source9, nameof(source9));
|
|
Error.ThrowArgumentNullException(source10, nameof(source10));
|
|
Error.ThrowArgumentNullException(source11, nameof(source11));
|
|
Error.ThrowArgumentNullException(source12, nameof(source12));
|
|
Error.ThrowArgumentNullException(source13, nameof(source13));
|
|
Error.ThrowArgumentNullException(source14, nameof(source14));
|
|
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
|
|
|
|
return new CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult>(source1, source2, source3, source4, source5, source6, source7, source8, source9, source10, source11, source12, source13, source14, resultSelector);
|
|
}
|
|
|
|
public static IUniTaskAsyncEnumerable<TResult> CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult>(this IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, IUniTaskAsyncEnumerable<T7> source7, IUniTaskAsyncEnumerable<T8> source8, IUniTaskAsyncEnumerable<T9> source9, IUniTaskAsyncEnumerable<T10> source10, IUniTaskAsyncEnumerable<T11> source11, IUniTaskAsyncEnumerable<T12> source12, IUniTaskAsyncEnumerable<T13> source13, IUniTaskAsyncEnumerable<T14> source14, IUniTaskAsyncEnumerable<T15> source15, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult> resultSelector)
|
|
{
|
|
Error.ThrowArgumentNullException(source1, nameof(source1));
|
|
Error.ThrowArgumentNullException(source2, nameof(source2));
|
|
Error.ThrowArgumentNullException(source3, nameof(source3));
|
|
Error.ThrowArgumentNullException(source4, nameof(source4));
|
|
Error.ThrowArgumentNullException(source5, nameof(source5));
|
|
Error.ThrowArgumentNullException(source6, nameof(source6));
|
|
Error.ThrowArgumentNullException(source7, nameof(source7));
|
|
Error.ThrowArgumentNullException(source8, nameof(source8));
|
|
Error.ThrowArgumentNullException(source9, nameof(source9));
|
|
Error.ThrowArgumentNullException(source10, nameof(source10));
|
|
Error.ThrowArgumentNullException(source11, nameof(source11));
|
|
Error.ThrowArgumentNullException(source12, nameof(source12));
|
|
Error.ThrowArgumentNullException(source13, nameof(source13));
|
|
Error.ThrowArgumentNullException(source14, nameof(source14));
|
|
Error.ThrowArgumentNullException(source15, nameof(source15));
|
|
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
|
|
|
|
return new CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult>(source1, source2, source3, source4, source5, source6, source7, source8, source9, source10, source11, source12, source13, source14, source15, resultSelector);
|
|
}
|
|
|
|
}
|
|
|
|
internal class CombineLatest<T1, T2, TResult> : IUniTaskAsyncEnumerable<TResult>
|
|
{
|
|
readonly IUniTaskAsyncEnumerable<T1> source1;
|
|
readonly IUniTaskAsyncEnumerable<T2> source2;
|
|
|
|
readonly Func<T1, T2, TResult> resultSelector;
|
|
|
|
public CombineLatest(IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, Func<T1, T2, TResult> resultSelector)
|
|
{
|
|
this.source1 = source1;
|
|
this.source2 = source2;
|
|
|
|
this.resultSelector = resultSelector;
|
|
}
|
|
|
|
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
|
{
|
|
return new _CombineLatest(source1, source2, resultSelector, cancellationToken);
|
|
}
|
|
|
|
class _CombineLatest : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
|
|
{
|
|
static readonly Action<object> Completed1Delegate = Completed1;
|
|
static readonly Action<object> Completed2Delegate = Completed2;
|
|
const int CompleteCount = 2;
|
|
|
|
readonly IUniTaskAsyncEnumerable<T1> source1;
|
|
readonly IUniTaskAsyncEnumerable<T2> source2;
|
|
|
|
readonly Func<T1, T2, TResult> resultSelector;
|
|
CancellationToken cancellationToken;
|
|
|
|
IUniTaskAsyncEnumerator<T1> enumerator1;
|
|
UniTask<bool>.Awaiter awaiter1;
|
|
bool hasCurrent1;
|
|
bool running1;
|
|
T1 current1;
|
|
|
|
IUniTaskAsyncEnumerator<T2> enumerator2;
|
|
UniTask<bool>.Awaiter awaiter2;
|
|
bool hasCurrent2;
|
|
bool running2;
|
|
T2 current2;
|
|
|
|
int completedCount;
|
|
bool syncRunning;
|
|
TResult result;
|
|
|
|
public _CombineLatest(IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, Func<T1, T2, TResult> resultSelector, CancellationToken cancellationToken)
|
|
{
|
|
this.source1 = source1;
|
|
this.source2 = source2;
|
|
|
|
this.resultSelector = resultSelector;
|
|
this.cancellationToken = cancellationToken;
|
|
TaskTracker.TrackActiveTask(this, 3);
|
|
}
|
|
|
|
public TResult Current => result;
|
|
|
|
public UniTask<bool> MoveNextAsync()
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
if (completedCount == CompleteCount) return CompletedTasks.False;
|
|
|
|
if (enumerator1 == null)
|
|
{
|
|
enumerator1 = source1.GetAsyncEnumerator(cancellationToken);
|
|
enumerator2 = source2.GetAsyncEnumerator(cancellationToken);
|
|
}
|
|
|
|
completionSource.Reset();
|
|
|
|
AGAIN:
|
|
syncRunning = true;
|
|
if (!running1)
|
|
{
|
|
running1 = true;
|
|
awaiter1 = enumerator1.MoveNextAsync().GetAwaiter();
|
|
if (awaiter1.IsCompleted)
|
|
{
|
|
Completed1(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter1.SourceOnCompleted(Completed1Delegate, this);
|
|
}
|
|
}
|
|
if (!running2)
|
|
{
|
|
running2 = true;
|
|
awaiter2 = enumerator2.MoveNextAsync().GetAwaiter();
|
|
if (awaiter2.IsCompleted)
|
|
{
|
|
Completed2(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter2.SourceOnCompleted(Completed2Delegate, this);
|
|
}
|
|
}
|
|
|
|
if (!running1 || !running2)
|
|
{
|
|
goto AGAIN;
|
|
}
|
|
syncRunning = false;
|
|
|
|
return new UniTask<bool>(this, completionSource.Version);
|
|
}
|
|
|
|
static void Completed1(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running1 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter1.GetResult())
|
|
{
|
|
self.hasCurrent1 = true;
|
|
self.current1 = self.enumerator1.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter1 = self.enumerator1.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter1.SourceOnCompleted(Completed1Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed2(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running2 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter2.GetResult())
|
|
{
|
|
self.hasCurrent2 = true;
|
|
self.current2 = self.enumerator2.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter2 = self.enumerator2.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter2.SourceOnCompleted(Completed2Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
bool TrySetResult()
|
|
{
|
|
if (hasCurrent1 && hasCurrent2)
|
|
{
|
|
result = resultSelector(current1, current2);
|
|
completionSource.TrySetResult(true);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async UniTask DisposeAsync()
|
|
{
|
|
TaskTracker.RemoveTracking(this);
|
|
if (enumerator1 != null)
|
|
{
|
|
await enumerator1.DisposeAsync();
|
|
}
|
|
if (enumerator2 != null)
|
|
{
|
|
await enumerator2.DisposeAsync();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
internal class CombineLatest<T1, T2, T3, TResult> : IUniTaskAsyncEnumerable<TResult>
|
|
{
|
|
readonly IUniTaskAsyncEnumerable<T1> source1;
|
|
readonly IUniTaskAsyncEnumerable<T2> source2;
|
|
readonly IUniTaskAsyncEnumerable<T3> source3;
|
|
|
|
readonly Func<T1, T2, T3, TResult> resultSelector;
|
|
|
|
public CombineLatest(IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, Func<T1, T2, T3, TResult> resultSelector)
|
|
{
|
|
this.source1 = source1;
|
|
this.source2 = source2;
|
|
this.source3 = source3;
|
|
|
|
this.resultSelector = resultSelector;
|
|
}
|
|
|
|
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
|
{
|
|
return new _CombineLatest(source1, source2, source3, resultSelector, cancellationToken);
|
|
}
|
|
|
|
class _CombineLatest : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
|
|
{
|
|
static readonly Action<object> Completed1Delegate = Completed1;
|
|
static readonly Action<object> Completed2Delegate = Completed2;
|
|
static readonly Action<object> Completed3Delegate = Completed3;
|
|
const int CompleteCount = 3;
|
|
|
|
readonly IUniTaskAsyncEnumerable<T1> source1;
|
|
readonly IUniTaskAsyncEnumerable<T2> source2;
|
|
readonly IUniTaskAsyncEnumerable<T3> source3;
|
|
|
|
readonly Func<T1, T2, T3, TResult> resultSelector;
|
|
CancellationToken cancellationToken;
|
|
|
|
IUniTaskAsyncEnumerator<T1> enumerator1;
|
|
UniTask<bool>.Awaiter awaiter1;
|
|
bool hasCurrent1;
|
|
bool running1;
|
|
T1 current1;
|
|
|
|
IUniTaskAsyncEnumerator<T2> enumerator2;
|
|
UniTask<bool>.Awaiter awaiter2;
|
|
bool hasCurrent2;
|
|
bool running2;
|
|
T2 current2;
|
|
|
|
IUniTaskAsyncEnumerator<T3> enumerator3;
|
|
UniTask<bool>.Awaiter awaiter3;
|
|
bool hasCurrent3;
|
|
bool running3;
|
|
T3 current3;
|
|
|
|
int completedCount;
|
|
bool syncRunning;
|
|
TResult result;
|
|
|
|
public _CombineLatest(IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, Func<T1, T2, T3, TResult> resultSelector, CancellationToken cancellationToken)
|
|
{
|
|
this.source1 = source1;
|
|
this.source2 = source2;
|
|
this.source3 = source3;
|
|
|
|
this.resultSelector = resultSelector;
|
|
this.cancellationToken = cancellationToken;
|
|
TaskTracker.TrackActiveTask(this, 3);
|
|
}
|
|
|
|
public TResult Current => result;
|
|
|
|
public UniTask<bool> MoveNextAsync()
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
if (completedCount == CompleteCount) return CompletedTasks.False;
|
|
|
|
if (enumerator1 == null)
|
|
{
|
|
enumerator1 = source1.GetAsyncEnumerator(cancellationToken);
|
|
enumerator2 = source2.GetAsyncEnumerator(cancellationToken);
|
|
enumerator3 = source3.GetAsyncEnumerator(cancellationToken);
|
|
}
|
|
|
|
completionSource.Reset();
|
|
|
|
AGAIN:
|
|
syncRunning = true;
|
|
if (!running1)
|
|
{
|
|
running1 = true;
|
|
awaiter1 = enumerator1.MoveNextAsync().GetAwaiter();
|
|
if (awaiter1.IsCompleted)
|
|
{
|
|
Completed1(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter1.SourceOnCompleted(Completed1Delegate, this);
|
|
}
|
|
}
|
|
if (!running2)
|
|
{
|
|
running2 = true;
|
|
awaiter2 = enumerator2.MoveNextAsync().GetAwaiter();
|
|
if (awaiter2.IsCompleted)
|
|
{
|
|
Completed2(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter2.SourceOnCompleted(Completed2Delegate, this);
|
|
}
|
|
}
|
|
if (!running3)
|
|
{
|
|
running3 = true;
|
|
awaiter3 = enumerator3.MoveNextAsync().GetAwaiter();
|
|
if (awaiter3.IsCompleted)
|
|
{
|
|
Completed3(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter3.SourceOnCompleted(Completed3Delegate, this);
|
|
}
|
|
}
|
|
|
|
if (!running1 || !running2 || !running3)
|
|
{
|
|
goto AGAIN;
|
|
}
|
|
syncRunning = false;
|
|
|
|
return new UniTask<bool>(this, completionSource.Version);
|
|
}
|
|
|
|
static void Completed1(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running1 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter1.GetResult())
|
|
{
|
|
self.hasCurrent1 = true;
|
|
self.current1 = self.enumerator1.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter1 = self.enumerator1.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter1.SourceOnCompleted(Completed1Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed2(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running2 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter2.GetResult())
|
|
{
|
|
self.hasCurrent2 = true;
|
|
self.current2 = self.enumerator2.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter2 = self.enumerator2.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter2.SourceOnCompleted(Completed2Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed3(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running3 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter3.GetResult())
|
|
{
|
|
self.hasCurrent3 = true;
|
|
self.current3 = self.enumerator3.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter3 = self.enumerator3.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter3.SourceOnCompleted(Completed3Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
bool TrySetResult()
|
|
{
|
|
if (hasCurrent1 && hasCurrent2 && hasCurrent3)
|
|
{
|
|
result = resultSelector(current1, current2, current3);
|
|
completionSource.TrySetResult(true);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async UniTask DisposeAsync()
|
|
{
|
|
TaskTracker.RemoveTracking(this);
|
|
if (enumerator1 != null)
|
|
{
|
|
await enumerator1.DisposeAsync();
|
|
}
|
|
if (enumerator2 != null)
|
|
{
|
|
await enumerator2.DisposeAsync();
|
|
}
|
|
if (enumerator3 != null)
|
|
{
|
|
await enumerator3.DisposeAsync();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
internal class CombineLatest<T1, T2, T3, T4, TResult> : IUniTaskAsyncEnumerable<TResult>
|
|
{
|
|
readonly IUniTaskAsyncEnumerable<T1> source1;
|
|
readonly IUniTaskAsyncEnumerable<T2> source2;
|
|
readonly IUniTaskAsyncEnumerable<T3> source3;
|
|
readonly IUniTaskAsyncEnumerable<T4> source4;
|
|
|
|
readonly Func<T1, T2, T3, T4, TResult> resultSelector;
|
|
|
|
public CombineLatest(IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, Func<T1, T2, T3, T4, TResult> resultSelector)
|
|
{
|
|
this.source1 = source1;
|
|
this.source2 = source2;
|
|
this.source3 = source3;
|
|
this.source4 = source4;
|
|
|
|
this.resultSelector = resultSelector;
|
|
}
|
|
|
|
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
|
{
|
|
return new _CombineLatest(source1, source2, source3, source4, resultSelector, cancellationToken);
|
|
}
|
|
|
|
class _CombineLatest : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
|
|
{
|
|
static readonly Action<object> Completed1Delegate = Completed1;
|
|
static readonly Action<object> Completed2Delegate = Completed2;
|
|
static readonly Action<object> Completed3Delegate = Completed3;
|
|
static readonly Action<object> Completed4Delegate = Completed4;
|
|
const int CompleteCount = 4;
|
|
|
|
readonly IUniTaskAsyncEnumerable<T1> source1;
|
|
readonly IUniTaskAsyncEnumerable<T2> source2;
|
|
readonly IUniTaskAsyncEnumerable<T3> source3;
|
|
readonly IUniTaskAsyncEnumerable<T4> source4;
|
|
|
|
readonly Func<T1, T2, T3, T4, TResult> resultSelector;
|
|
CancellationToken cancellationToken;
|
|
|
|
IUniTaskAsyncEnumerator<T1> enumerator1;
|
|
UniTask<bool>.Awaiter awaiter1;
|
|
bool hasCurrent1;
|
|
bool running1;
|
|
T1 current1;
|
|
|
|
IUniTaskAsyncEnumerator<T2> enumerator2;
|
|
UniTask<bool>.Awaiter awaiter2;
|
|
bool hasCurrent2;
|
|
bool running2;
|
|
T2 current2;
|
|
|
|
IUniTaskAsyncEnumerator<T3> enumerator3;
|
|
UniTask<bool>.Awaiter awaiter3;
|
|
bool hasCurrent3;
|
|
bool running3;
|
|
T3 current3;
|
|
|
|
IUniTaskAsyncEnumerator<T4> enumerator4;
|
|
UniTask<bool>.Awaiter awaiter4;
|
|
bool hasCurrent4;
|
|
bool running4;
|
|
T4 current4;
|
|
|
|
int completedCount;
|
|
bool syncRunning;
|
|
TResult result;
|
|
|
|
public _CombineLatest(IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, Func<T1, T2, T3, T4, TResult> resultSelector, CancellationToken cancellationToken)
|
|
{
|
|
this.source1 = source1;
|
|
this.source2 = source2;
|
|
this.source3 = source3;
|
|
this.source4 = source4;
|
|
|
|
this.resultSelector = resultSelector;
|
|
this.cancellationToken = cancellationToken;
|
|
TaskTracker.TrackActiveTask(this, 3);
|
|
}
|
|
|
|
public TResult Current => result;
|
|
|
|
public UniTask<bool> MoveNextAsync()
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
if (completedCount == CompleteCount) return CompletedTasks.False;
|
|
|
|
if (enumerator1 == null)
|
|
{
|
|
enumerator1 = source1.GetAsyncEnumerator(cancellationToken);
|
|
enumerator2 = source2.GetAsyncEnumerator(cancellationToken);
|
|
enumerator3 = source3.GetAsyncEnumerator(cancellationToken);
|
|
enumerator4 = source4.GetAsyncEnumerator(cancellationToken);
|
|
}
|
|
|
|
completionSource.Reset();
|
|
|
|
AGAIN:
|
|
syncRunning = true;
|
|
if (!running1)
|
|
{
|
|
running1 = true;
|
|
awaiter1 = enumerator1.MoveNextAsync().GetAwaiter();
|
|
if (awaiter1.IsCompleted)
|
|
{
|
|
Completed1(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter1.SourceOnCompleted(Completed1Delegate, this);
|
|
}
|
|
}
|
|
if (!running2)
|
|
{
|
|
running2 = true;
|
|
awaiter2 = enumerator2.MoveNextAsync().GetAwaiter();
|
|
if (awaiter2.IsCompleted)
|
|
{
|
|
Completed2(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter2.SourceOnCompleted(Completed2Delegate, this);
|
|
}
|
|
}
|
|
if (!running3)
|
|
{
|
|
running3 = true;
|
|
awaiter3 = enumerator3.MoveNextAsync().GetAwaiter();
|
|
if (awaiter3.IsCompleted)
|
|
{
|
|
Completed3(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter3.SourceOnCompleted(Completed3Delegate, this);
|
|
}
|
|
}
|
|
if (!running4)
|
|
{
|
|
running4 = true;
|
|
awaiter4 = enumerator4.MoveNextAsync().GetAwaiter();
|
|
if (awaiter4.IsCompleted)
|
|
{
|
|
Completed4(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter4.SourceOnCompleted(Completed4Delegate, this);
|
|
}
|
|
}
|
|
|
|
if (!running1 || !running2 || !running3 || !running4)
|
|
{
|
|
goto AGAIN;
|
|
}
|
|
syncRunning = false;
|
|
|
|
return new UniTask<bool>(this, completionSource.Version);
|
|
}
|
|
|
|
static void Completed1(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running1 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter1.GetResult())
|
|
{
|
|
self.hasCurrent1 = true;
|
|
self.current1 = self.enumerator1.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter1 = self.enumerator1.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter1.SourceOnCompleted(Completed1Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed2(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running2 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter2.GetResult())
|
|
{
|
|
self.hasCurrent2 = true;
|
|
self.current2 = self.enumerator2.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter2 = self.enumerator2.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter2.SourceOnCompleted(Completed2Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed3(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running3 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter3.GetResult())
|
|
{
|
|
self.hasCurrent3 = true;
|
|
self.current3 = self.enumerator3.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter3 = self.enumerator3.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter3.SourceOnCompleted(Completed3Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed4(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running4 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter4.GetResult())
|
|
{
|
|
self.hasCurrent4 = true;
|
|
self.current4 = self.enumerator4.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter4 = self.enumerator4.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter4.SourceOnCompleted(Completed4Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
bool TrySetResult()
|
|
{
|
|
if (hasCurrent1 && hasCurrent2 && hasCurrent3 && hasCurrent4)
|
|
{
|
|
result = resultSelector(current1, current2, current3, current4);
|
|
completionSource.TrySetResult(true);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async UniTask DisposeAsync()
|
|
{
|
|
TaskTracker.RemoveTracking(this);
|
|
if (enumerator1 != null)
|
|
{
|
|
await enumerator1.DisposeAsync();
|
|
}
|
|
if (enumerator2 != null)
|
|
{
|
|
await enumerator2.DisposeAsync();
|
|
}
|
|
if (enumerator3 != null)
|
|
{
|
|
await enumerator3.DisposeAsync();
|
|
}
|
|
if (enumerator4 != null)
|
|
{
|
|
await enumerator4.DisposeAsync();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
internal class CombineLatest<T1, T2, T3, T4, T5, TResult> : IUniTaskAsyncEnumerable<TResult>
|
|
{
|
|
readonly IUniTaskAsyncEnumerable<T1> source1;
|
|
readonly IUniTaskAsyncEnumerable<T2> source2;
|
|
readonly IUniTaskAsyncEnumerable<T3> source3;
|
|
readonly IUniTaskAsyncEnumerable<T4> source4;
|
|
readonly IUniTaskAsyncEnumerable<T5> source5;
|
|
|
|
readonly Func<T1, T2, T3, T4, T5, TResult> resultSelector;
|
|
|
|
public CombineLatest(IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, Func<T1, T2, T3, T4, T5, TResult> resultSelector)
|
|
{
|
|
this.source1 = source1;
|
|
this.source2 = source2;
|
|
this.source3 = source3;
|
|
this.source4 = source4;
|
|
this.source5 = source5;
|
|
|
|
this.resultSelector = resultSelector;
|
|
}
|
|
|
|
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
|
{
|
|
return new _CombineLatest(source1, source2, source3, source4, source5, resultSelector, cancellationToken);
|
|
}
|
|
|
|
class _CombineLatest : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
|
|
{
|
|
static readonly Action<object> Completed1Delegate = Completed1;
|
|
static readonly Action<object> Completed2Delegate = Completed2;
|
|
static readonly Action<object> Completed3Delegate = Completed3;
|
|
static readonly Action<object> Completed4Delegate = Completed4;
|
|
static readonly Action<object> Completed5Delegate = Completed5;
|
|
const int CompleteCount = 5;
|
|
|
|
readonly IUniTaskAsyncEnumerable<T1> source1;
|
|
readonly IUniTaskAsyncEnumerable<T2> source2;
|
|
readonly IUniTaskAsyncEnumerable<T3> source3;
|
|
readonly IUniTaskAsyncEnumerable<T4> source4;
|
|
readonly IUniTaskAsyncEnumerable<T5> source5;
|
|
|
|
readonly Func<T1, T2, T3, T4, T5, TResult> resultSelector;
|
|
CancellationToken cancellationToken;
|
|
|
|
IUniTaskAsyncEnumerator<T1> enumerator1;
|
|
UniTask<bool>.Awaiter awaiter1;
|
|
bool hasCurrent1;
|
|
bool running1;
|
|
T1 current1;
|
|
|
|
IUniTaskAsyncEnumerator<T2> enumerator2;
|
|
UniTask<bool>.Awaiter awaiter2;
|
|
bool hasCurrent2;
|
|
bool running2;
|
|
T2 current2;
|
|
|
|
IUniTaskAsyncEnumerator<T3> enumerator3;
|
|
UniTask<bool>.Awaiter awaiter3;
|
|
bool hasCurrent3;
|
|
bool running3;
|
|
T3 current3;
|
|
|
|
IUniTaskAsyncEnumerator<T4> enumerator4;
|
|
UniTask<bool>.Awaiter awaiter4;
|
|
bool hasCurrent4;
|
|
bool running4;
|
|
T4 current4;
|
|
|
|
IUniTaskAsyncEnumerator<T5> enumerator5;
|
|
UniTask<bool>.Awaiter awaiter5;
|
|
bool hasCurrent5;
|
|
bool running5;
|
|
T5 current5;
|
|
|
|
int completedCount;
|
|
bool syncRunning;
|
|
TResult result;
|
|
|
|
public _CombineLatest(IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, Func<T1, T2, T3, T4, T5, TResult> resultSelector, CancellationToken cancellationToken)
|
|
{
|
|
this.source1 = source1;
|
|
this.source2 = source2;
|
|
this.source3 = source3;
|
|
this.source4 = source4;
|
|
this.source5 = source5;
|
|
|
|
this.resultSelector = resultSelector;
|
|
this.cancellationToken = cancellationToken;
|
|
TaskTracker.TrackActiveTask(this, 3);
|
|
}
|
|
|
|
public TResult Current => result;
|
|
|
|
public UniTask<bool> MoveNextAsync()
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
if (completedCount == CompleteCount) return CompletedTasks.False;
|
|
|
|
if (enumerator1 == null)
|
|
{
|
|
enumerator1 = source1.GetAsyncEnumerator(cancellationToken);
|
|
enumerator2 = source2.GetAsyncEnumerator(cancellationToken);
|
|
enumerator3 = source3.GetAsyncEnumerator(cancellationToken);
|
|
enumerator4 = source4.GetAsyncEnumerator(cancellationToken);
|
|
enumerator5 = source5.GetAsyncEnumerator(cancellationToken);
|
|
}
|
|
|
|
completionSource.Reset();
|
|
|
|
AGAIN:
|
|
syncRunning = true;
|
|
if (!running1)
|
|
{
|
|
running1 = true;
|
|
awaiter1 = enumerator1.MoveNextAsync().GetAwaiter();
|
|
if (awaiter1.IsCompleted)
|
|
{
|
|
Completed1(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter1.SourceOnCompleted(Completed1Delegate, this);
|
|
}
|
|
}
|
|
if (!running2)
|
|
{
|
|
running2 = true;
|
|
awaiter2 = enumerator2.MoveNextAsync().GetAwaiter();
|
|
if (awaiter2.IsCompleted)
|
|
{
|
|
Completed2(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter2.SourceOnCompleted(Completed2Delegate, this);
|
|
}
|
|
}
|
|
if (!running3)
|
|
{
|
|
running3 = true;
|
|
awaiter3 = enumerator3.MoveNextAsync().GetAwaiter();
|
|
if (awaiter3.IsCompleted)
|
|
{
|
|
Completed3(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter3.SourceOnCompleted(Completed3Delegate, this);
|
|
}
|
|
}
|
|
if (!running4)
|
|
{
|
|
running4 = true;
|
|
awaiter4 = enumerator4.MoveNextAsync().GetAwaiter();
|
|
if (awaiter4.IsCompleted)
|
|
{
|
|
Completed4(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter4.SourceOnCompleted(Completed4Delegate, this);
|
|
}
|
|
}
|
|
if (!running5)
|
|
{
|
|
running5 = true;
|
|
awaiter5 = enumerator5.MoveNextAsync().GetAwaiter();
|
|
if (awaiter5.IsCompleted)
|
|
{
|
|
Completed5(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter5.SourceOnCompleted(Completed5Delegate, this);
|
|
}
|
|
}
|
|
|
|
if (!running1 || !running2 || !running3 || !running4 || !running5)
|
|
{
|
|
goto AGAIN;
|
|
}
|
|
syncRunning = false;
|
|
|
|
return new UniTask<bool>(this, completionSource.Version);
|
|
}
|
|
|
|
static void Completed1(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running1 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter1.GetResult())
|
|
{
|
|
self.hasCurrent1 = true;
|
|
self.current1 = self.enumerator1.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter1 = self.enumerator1.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter1.SourceOnCompleted(Completed1Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed2(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running2 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter2.GetResult())
|
|
{
|
|
self.hasCurrent2 = true;
|
|
self.current2 = self.enumerator2.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter2 = self.enumerator2.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter2.SourceOnCompleted(Completed2Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed3(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running3 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter3.GetResult())
|
|
{
|
|
self.hasCurrent3 = true;
|
|
self.current3 = self.enumerator3.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter3 = self.enumerator3.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter3.SourceOnCompleted(Completed3Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed4(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running4 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter4.GetResult())
|
|
{
|
|
self.hasCurrent4 = true;
|
|
self.current4 = self.enumerator4.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter4 = self.enumerator4.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter4.SourceOnCompleted(Completed4Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed5(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running5 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter5.GetResult())
|
|
{
|
|
self.hasCurrent5 = true;
|
|
self.current5 = self.enumerator5.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter5 = self.enumerator5.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter5.SourceOnCompleted(Completed5Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
bool TrySetResult()
|
|
{
|
|
if (hasCurrent1 && hasCurrent2 && hasCurrent3 && hasCurrent4 && hasCurrent5)
|
|
{
|
|
result = resultSelector(current1, current2, current3, current4, current5);
|
|
completionSource.TrySetResult(true);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async UniTask DisposeAsync()
|
|
{
|
|
TaskTracker.RemoveTracking(this);
|
|
if (enumerator1 != null)
|
|
{
|
|
await enumerator1.DisposeAsync();
|
|
}
|
|
if (enumerator2 != null)
|
|
{
|
|
await enumerator2.DisposeAsync();
|
|
}
|
|
if (enumerator3 != null)
|
|
{
|
|
await enumerator3.DisposeAsync();
|
|
}
|
|
if (enumerator4 != null)
|
|
{
|
|
await enumerator4.DisposeAsync();
|
|
}
|
|
if (enumerator5 != null)
|
|
{
|
|
await enumerator5.DisposeAsync();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
internal class CombineLatest<T1, T2, T3, T4, T5, T6, TResult> : IUniTaskAsyncEnumerable<TResult>
|
|
{
|
|
readonly IUniTaskAsyncEnumerable<T1> source1;
|
|
readonly IUniTaskAsyncEnumerable<T2> source2;
|
|
readonly IUniTaskAsyncEnumerable<T3> source3;
|
|
readonly IUniTaskAsyncEnumerable<T4> source4;
|
|
readonly IUniTaskAsyncEnumerable<T5> source5;
|
|
readonly IUniTaskAsyncEnumerable<T6> source6;
|
|
|
|
readonly Func<T1, T2, T3, T4, T5, T6, TResult> resultSelector;
|
|
|
|
public CombineLatest(IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, Func<T1, T2, T3, T4, T5, T6, TResult> resultSelector)
|
|
{
|
|
this.source1 = source1;
|
|
this.source2 = source2;
|
|
this.source3 = source3;
|
|
this.source4 = source4;
|
|
this.source5 = source5;
|
|
this.source6 = source6;
|
|
|
|
this.resultSelector = resultSelector;
|
|
}
|
|
|
|
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
|
{
|
|
return new _CombineLatest(source1, source2, source3, source4, source5, source6, resultSelector, cancellationToken);
|
|
}
|
|
|
|
class _CombineLatest : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
|
|
{
|
|
static readonly Action<object> Completed1Delegate = Completed1;
|
|
static readonly Action<object> Completed2Delegate = Completed2;
|
|
static readonly Action<object> Completed3Delegate = Completed3;
|
|
static readonly Action<object> Completed4Delegate = Completed4;
|
|
static readonly Action<object> Completed5Delegate = Completed5;
|
|
static readonly Action<object> Completed6Delegate = Completed6;
|
|
const int CompleteCount = 6;
|
|
|
|
readonly IUniTaskAsyncEnumerable<T1> source1;
|
|
readonly IUniTaskAsyncEnumerable<T2> source2;
|
|
readonly IUniTaskAsyncEnumerable<T3> source3;
|
|
readonly IUniTaskAsyncEnumerable<T4> source4;
|
|
readonly IUniTaskAsyncEnumerable<T5> source5;
|
|
readonly IUniTaskAsyncEnumerable<T6> source6;
|
|
|
|
readonly Func<T1, T2, T3, T4, T5, T6, TResult> resultSelector;
|
|
CancellationToken cancellationToken;
|
|
|
|
IUniTaskAsyncEnumerator<T1> enumerator1;
|
|
UniTask<bool>.Awaiter awaiter1;
|
|
bool hasCurrent1;
|
|
bool running1;
|
|
T1 current1;
|
|
|
|
IUniTaskAsyncEnumerator<T2> enumerator2;
|
|
UniTask<bool>.Awaiter awaiter2;
|
|
bool hasCurrent2;
|
|
bool running2;
|
|
T2 current2;
|
|
|
|
IUniTaskAsyncEnumerator<T3> enumerator3;
|
|
UniTask<bool>.Awaiter awaiter3;
|
|
bool hasCurrent3;
|
|
bool running3;
|
|
T3 current3;
|
|
|
|
IUniTaskAsyncEnumerator<T4> enumerator4;
|
|
UniTask<bool>.Awaiter awaiter4;
|
|
bool hasCurrent4;
|
|
bool running4;
|
|
T4 current4;
|
|
|
|
IUniTaskAsyncEnumerator<T5> enumerator5;
|
|
UniTask<bool>.Awaiter awaiter5;
|
|
bool hasCurrent5;
|
|
bool running5;
|
|
T5 current5;
|
|
|
|
IUniTaskAsyncEnumerator<T6> enumerator6;
|
|
UniTask<bool>.Awaiter awaiter6;
|
|
bool hasCurrent6;
|
|
bool running6;
|
|
T6 current6;
|
|
|
|
int completedCount;
|
|
bool syncRunning;
|
|
TResult result;
|
|
|
|
public _CombineLatest(IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, Func<T1, T2, T3, T4, T5, T6, TResult> resultSelector, CancellationToken cancellationToken)
|
|
{
|
|
this.source1 = source1;
|
|
this.source2 = source2;
|
|
this.source3 = source3;
|
|
this.source4 = source4;
|
|
this.source5 = source5;
|
|
this.source6 = source6;
|
|
|
|
this.resultSelector = resultSelector;
|
|
this.cancellationToken = cancellationToken;
|
|
TaskTracker.TrackActiveTask(this, 3);
|
|
}
|
|
|
|
public TResult Current => result;
|
|
|
|
public UniTask<bool> MoveNextAsync()
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
if (completedCount == CompleteCount) return CompletedTasks.False;
|
|
|
|
if (enumerator1 == null)
|
|
{
|
|
enumerator1 = source1.GetAsyncEnumerator(cancellationToken);
|
|
enumerator2 = source2.GetAsyncEnumerator(cancellationToken);
|
|
enumerator3 = source3.GetAsyncEnumerator(cancellationToken);
|
|
enumerator4 = source4.GetAsyncEnumerator(cancellationToken);
|
|
enumerator5 = source5.GetAsyncEnumerator(cancellationToken);
|
|
enumerator6 = source6.GetAsyncEnumerator(cancellationToken);
|
|
}
|
|
|
|
completionSource.Reset();
|
|
|
|
AGAIN:
|
|
syncRunning = true;
|
|
if (!running1)
|
|
{
|
|
running1 = true;
|
|
awaiter1 = enumerator1.MoveNextAsync().GetAwaiter();
|
|
if (awaiter1.IsCompleted)
|
|
{
|
|
Completed1(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter1.SourceOnCompleted(Completed1Delegate, this);
|
|
}
|
|
}
|
|
if (!running2)
|
|
{
|
|
running2 = true;
|
|
awaiter2 = enumerator2.MoveNextAsync().GetAwaiter();
|
|
if (awaiter2.IsCompleted)
|
|
{
|
|
Completed2(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter2.SourceOnCompleted(Completed2Delegate, this);
|
|
}
|
|
}
|
|
if (!running3)
|
|
{
|
|
running3 = true;
|
|
awaiter3 = enumerator3.MoveNextAsync().GetAwaiter();
|
|
if (awaiter3.IsCompleted)
|
|
{
|
|
Completed3(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter3.SourceOnCompleted(Completed3Delegate, this);
|
|
}
|
|
}
|
|
if (!running4)
|
|
{
|
|
running4 = true;
|
|
awaiter4 = enumerator4.MoveNextAsync().GetAwaiter();
|
|
if (awaiter4.IsCompleted)
|
|
{
|
|
Completed4(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter4.SourceOnCompleted(Completed4Delegate, this);
|
|
}
|
|
}
|
|
if (!running5)
|
|
{
|
|
running5 = true;
|
|
awaiter5 = enumerator5.MoveNextAsync().GetAwaiter();
|
|
if (awaiter5.IsCompleted)
|
|
{
|
|
Completed5(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter5.SourceOnCompleted(Completed5Delegate, this);
|
|
}
|
|
}
|
|
if (!running6)
|
|
{
|
|
running6 = true;
|
|
awaiter6 = enumerator6.MoveNextAsync().GetAwaiter();
|
|
if (awaiter6.IsCompleted)
|
|
{
|
|
Completed6(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter6.SourceOnCompleted(Completed6Delegate, this);
|
|
}
|
|
}
|
|
|
|
if (!running1 || !running2 || !running3 || !running4 || !running5 || !running6)
|
|
{
|
|
goto AGAIN;
|
|
}
|
|
syncRunning = false;
|
|
|
|
return new UniTask<bool>(this, completionSource.Version);
|
|
}
|
|
|
|
static void Completed1(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running1 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter1.GetResult())
|
|
{
|
|
self.hasCurrent1 = true;
|
|
self.current1 = self.enumerator1.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter1 = self.enumerator1.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter1.SourceOnCompleted(Completed1Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed2(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running2 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter2.GetResult())
|
|
{
|
|
self.hasCurrent2 = true;
|
|
self.current2 = self.enumerator2.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter2 = self.enumerator2.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter2.SourceOnCompleted(Completed2Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed3(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running3 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter3.GetResult())
|
|
{
|
|
self.hasCurrent3 = true;
|
|
self.current3 = self.enumerator3.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter3 = self.enumerator3.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter3.SourceOnCompleted(Completed3Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed4(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running4 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter4.GetResult())
|
|
{
|
|
self.hasCurrent4 = true;
|
|
self.current4 = self.enumerator4.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter4 = self.enumerator4.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter4.SourceOnCompleted(Completed4Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed5(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running5 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter5.GetResult())
|
|
{
|
|
self.hasCurrent5 = true;
|
|
self.current5 = self.enumerator5.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter5 = self.enumerator5.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter5.SourceOnCompleted(Completed5Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed6(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running6 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter6.GetResult())
|
|
{
|
|
self.hasCurrent6 = true;
|
|
self.current6 = self.enumerator6.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter6 = self.enumerator6.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter6.SourceOnCompleted(Completed6Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
bool TrySetResult()
|
|
{
|
|
if (hasCurrent1 && hasCurrent2 && hasCurrent3 && hasCurrent4 && hasCurrent5 && hasCurrent6)
|
|
{
|
|
result = resultSelector(current1, current2, current3, current4, current5, current6);
|
|
completionSource.TrySetResult(true);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async UniTask DisposeAsync()
|
|
{
|
|
TaskTracker.RemoveTracking(this);
|
|
if (enumerator1 != null)
|
|
{
|
|
await enumerator1.DisposeAsync();
|
|
}
|
|
if (enumerator2 != null)
|
|
{
|
|
await enumerator2.DisposeAsync();
|
|
}
|
|
if (enumerator3 != null)
|
|
{
|
|
await enumerator3.DisposeAsync();
|
|
}
|
|
if (enumerator4 != null)
|
|
{
|
|
await enumerator4.DisposeAsync();
|
|
}
|
|
if (enumerator5 != null)
|
|
{
|
|
await enumerator5.DisposeAsync();
|
|
}
|
|
if (enumerator6 != null)
|
|
{
|
|
await enumerator6.DisposeAsync();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
internal class CombineLatest<T1, T2, T3, T4, T5, T6, T7, TResult> : IUniTaskAsyncEnumerable<TResult>
|
|
{
|
|
readonly IUniTaskAsyncEnumerable<T1> source1;
|
|
readonly IUniTaskAsyncEnumerable<T2> source2;
|
|
readonly IUniTaskAsyncEnumerable<T3> source3;
|
|
readonly IUniTaskAsyncEnumerable<T4> source4;
|
|
readonly IUniTaskAsyncEnumerable<T5> source5;
|
|
readonly IUniTaskAsyncEnumerable<T6> source6;
|
|
readonly IUniTaskAsyncEnumerable<T7> source7;
|
|
|
|
readonly Func<T1, T2, T3, T4, T5, T6, T7, TResult> resultSelector;
|
|
|
|
public CombineLatest(IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, IUniTaskAsyncEnumerable<T7> source7, Func<T1, T2, T3, T4, T5, T6, T7, TResult> resultSelector)
|
|
{
|
|
this.source1 = source1;
|
|
this.source2 = source2;
|
|
this.source3 = source3;
|
|
this.source4 = source4;
|
|
this.source5 = source5;
|
|
this.source6 = source6;
|
|
this.source7 = source7;
|
|
|
|
this.resultSelector = resultSelector;
|
|
}
|
|
|
|
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
|
{
|
|
return new _CombineLatest(source1, source2, source3, source4, source5, source6, source7, resultSelector, cancellationToken);
|
|
}
|
|
|
|
class _CombineLatest : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
|
|
{
|
|
static readonly Action<object> Completed1Delegate = Completed1;
|
|
static readonly Action<object> Completed2Delegate = Completed2;
|
|
static readonly Action<object> Completed3Delegate = Completed3;
|
|
static readonly Action<object> Completed4Delegate = Completed4;
|
|
static readonly Action<object> Completed5Delegate = Completed5;
|
|
static readonly Action<object> Completed6Delegate = Completed6;
|
|
static readonly Action<object> Completed7Delegate = Completed7;
|
|
const int CompleteCount = 7;
|
|
|
|
readonly IUniTaskAsyncEnumerable<T1> source1;
|
|
readonly IUniTaskAsyncEnumerable<T2> source2;
|
|
readonly IUniTaskAsyncEnumerable<T3> source3;
|
|
readonly IUniTaskAsyncEnumerable<T4> source4;
|
|
readonly IUniTaskAsyncEnumerable<T5> source5;
|
|
readonly IUniTaskAsyncEnumerable<T6> source6;
|
|
readonly IUniTaskAsyncEnumerable<T7> source7;
|
|
|
|
readonly Func<T1, T2, T3, T4, T5, T6, T7, TResult> resultSelector;
|
|
CancellationToken cancellationToken;
|
|
|
|
IUniTaskAsyncEnumerator<T1> enumerator1;
|
|
UniTask<bool>.Awaiter awaiter1;
|
|
bool hasCurrent1;
|
|
bool running1;
|
|
T1 current1;
|
|
|
|
IUniTaskAsyncEnumerator<T2> enumerator2;
|
|
UniTask<bool>.Awaiter awaiter2;
|
|
bool hasCurrent2;
|
|
bool running2;
|
|
T2 current2;
|
|
|
|
IUniTaskAsyncEnumerator<T3> enumerator3;
|
|
UniTask<bool>.Awaiter awaiter3;
|
|
bool hasCurrent3;
|
|
bool running3;
|
|
T3 current3;
|
|
|
|
IUniTaskAsyncEnumerator<T4> enumerator4;
|
|
UniTask<bool>.Awaiter awaiter4;
|
|
bool hasCurrent4;
|
|
bool running4;
|
|
T4 current4;
|
|
|
|
IUniTaskAsyncEnumerator<T5> enumerator5;
|
|
UniTask<bool>.Awaiter awaiter5;
|
|
bool hasCurrent5;
|
|
bool running5;
|
|
T5 current5;
|
|
|
|
IUniTaskAsyncEnumerator<T6> enumerator6;
|
|
UniTask<bool>.Awaiter awaiter6;
|
|
bool hasCurrent6;
|
|
bool running6;
|
|
T6 current6;
|
|
|
|
IUniTaskAsyncEnumerator<T7> enumerator7;
|
|
UniTask<bool>.Awaiter awaiter7;
|
|
bool hasCurrent7;
|
|
bool running7;
|
|
T7 current7;
|
|
|
|
int completedCount;
|
|
bool syncRunning;
|
|
TResult result;
|
|
|
|
public _CombineLatest(IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, IUniTaskAsyncEnumerable<T7> source7, Func<T1, T2, T3, T4, T5, T6, T7, TResult> resultSelector, CancellationToken cancellationToken)
|
|
{
|
|
this.source1 = source1;
|
|
this.source2 = source2;
|
|
this.source3 = source3;
|
|
this.source4 = source4;
|
|
this.source5 = source5;
|
|
this.source6 = source6;
|
|
this.source7 = source7;
|
|
|
|
this.resultSelector = resultSelector;
|
|
this.cancellationToken = cancellationToken;
|
|
TaskTracker.TrackActiveTask(this, 3);
|
|
}
|
|
|
|
public TResult Current => result;
|
|
|
|
public UniTask<bool> MoveNextAsync()
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
if (completedCount == CompleteCount) return CompletedTasks.False;
|
|
|
|
if (enumerator1 == null)
|
|
{
|
|
enumerator1 = source1.GetAsyncEnumerator(cancellationToken);
|
|
enumerator2 = source2.GetAsyncEnumerator(cancellationToken);
|
|
enumerator3 = source3.GetAsyncEnumerator(cancellationToken);
|
|
enumerator4 = source4.GetAsyncEnumerator(cancellationToken);
|
|
enumerator5 = source5.GetAsyncEnumerator(cancellationToken);
|
|
enumerator6 = source6.GetAsyncEnumerator(cancellationToken);
|
|
enumerator7 = source7.GetAsyncEnumerator(cancellationToken);
|
|
}
|
|
|
|
completionSource.Reset();
|
|
|
|
AGAIN:
|
|
syncRunning = true;
|
|
if (!running1)
|
|
{
|
|
running1 = true;
|
|
awaiter1 = enumerator1.MoveNextAsync().GetAwaiter();
|
|
if (awaiter1.IsCompleted)
|
|
{
|
|
Completed1(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter1.SourceOnCompleted(Completed1Delegate, this);
|
|
}
|
|
}
|
|
if (!running2)
|
|
{
|
|
running2 = true;
|
|
awaiter2 = enumerator2.MoveNextAsync().GetAwaiter();
|
|
if (awaiter2.IsCompleted)
|
|
{
|
|
Completed2(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter2.SourceOnCompleted(Completed2Delegate, this);
|
|
}
|
|
}
|
|
if (!running3)
|
|
{
|
|
running3 = true;
|
|
awaiter3 = enumerator3.MoveNextAsync().GetAwaiter();
|
|
if (awaiter3.IsCompleted)
|
|
{
|
|
Completed3(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter3.SourceOnCompleted(Completed3Delegate, this);
|
|
}
|
|
}
|
|
if (!running4)
|
|
{
|
|
running4 = true;
|
|
awaiter4 = enumerator4.MoveNextAsync().GetAwaiter();
|
|
if (awaiter4.IsCompleted)
|
|
{
|
|
Completed4(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter4.SourceOnCompleted(Completed4Delegate, this);
|
|
}
|
|
}
|
|
if (!running5)
|
|
{
|
|
running5 = true;
|
|
awaiter5 = enumerator5.MoveNextAsync().GetAwaiter();
|
|
if (awaiter5.IsCompleted)
|
|
{
|
|
Completed5(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter5.SourceOnCompleted(Completed5Delegate, this);
|
|
}
|
|
}
|
|
if (!running6)
|
|
{
|
|
running6 = true;
|
|
awaiter6 = enumerator6.MoveNextAsync().GetAwaiter();
|
|
if (awaiter6.IsCompleted)
|
|
{
|
|
Completed6(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter6.SourceOnCompleted(Completed6Delegate, this);
|
|
}
|
|
}
|
|
if (!running7)
|
|
{
|
|
running7 = true;
|
|
awaiter7 = enumerator7.MoveNextAsync().GetAwaiter();
|
|
if (awaiter7.IsCompleted)
|
|
{
|
|
Completed7(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter7.SourceOnCompleted(Completed7Delegate, this);
|
|
}
|
|
}
|
|
|
|
if (!running1 || !running2 || !running3 || !running4 || !running5 || !running6 || !running7)
|
|
{
|
|
goto AGAIN;
|
|
}
|
|
syncRunning = false;
|
|
|
|
return new UniTask<bool>(this, completionSource.Version);
|
|
}
|
|
|
|
static void Completed1(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running1 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter1.GetResult())
|
|
{
|
|
self.hasCurrent1 = true;
|
|
self.current1 = self.enumerator1.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter1 = self.enumerator1.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter1.SourceOnCompleted(Completed1Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed2(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running2 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter2.GetResult())
|
|
{
|
|
self.hasCurrent2 = true;
|
|
self.current2 = self.enumerator2.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter2 = self.enumerator2.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter2.SourceOnCompleted(Completed2Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed3(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running3 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter3.GetResult())
|
|
{
|
|
self.hasCurrent3 = true;
|
|
self.current3 = self.enumerator3.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter3 = self.enumerator3.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter3.SourceOnCompleted(Completed3Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed4(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running4 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter4.GetResult())
|
|
{
|
|
self.hasCurrent4 = true;
|
|
self.current4 = self.enumerator4.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter4 = self.enumerator4.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter4.SourceOnCompleted(Completed4Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed5(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running5 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter5.GetResult())
|
|
{
|
|
self.hasCurrent5 = true;
|
|
self.current5 = self.enumerator5.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter5 = self.enumerator5.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter5.SourceOnCompleted(Completed5Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed6(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running6 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter6.GetResult())
|
|
{
|
|
self.hasCurrent6 = true;
|
|
self.current6 = self.enumerator6.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter6 = self.enumerator6.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter6.SourceOnCompleted(Completed6Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed7(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running7 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter7.GetResult())
|
|
{
|
|
self.hasCurrent7 = true;
|
|
self.current7 = self.enumerator7.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running7 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running7 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running7 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter7 = self.enumerator7.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter7.SourceOnCompleted(Completed7Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
bool TrySetResult()
|
|
{
|
|
if (hasCurrent1 && hasCurrent2 && hasCurrent3 && hasCurrent4 && hasCurrent5 && hasCurrent6 && hasCurrent7)
|
|
{
|
|
result = resultSelector(current1, current2, current3, current4, current5, current6, current7);
|
|
completionSource.TrySetResult(true);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async UniTask DisposeAsync()
|
|
{
|
|
TaskTracker.RemoveTracking(this);
|
|
if (enumerator1 != null)
|
|
{
|
|
await enumerator1.DisposeAsync();
|
|
}
|
|
if (enumerator2 != null)
|
|
{
|
|
await enumerator2.DisposeAsync();
|
|
}
|
|
if (enumerator3 != null)
|
|
{
|
|
await enumerator3.DisposeAsync();
|
|
}
|
|
if (enumerator4 != null)
|
|
{
|
|
await enumerator4.DisposeAsync();
|
|
}
|
|
if (enumerator5 != null)
|
|
{
|
|
await enumerator5.DisposeAsync();
|
|
}
|
|
if (enumerator6 != null)
|
|
{
|
|
await enumerator6.DisposeAsync();
|
|
}
|
|
if (enumerator7 != null)
|
|
{
|
|
await enumerator7.DisposeAsync();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
internal class CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, TResult> : IUniTaskAsyncEnumerable<TResult>
|
|
{
|
|
readonly IUniTaskAsyncEnumerable<T1> source1;
|
|
readonly IUniTaskAsyncEnumerable<T2> source2;
|
|
readonly IUniTaskAsyncEnumerable<T3> source3;
|
|
readonly IUniTaskAsyncEnumerable<T4> source4;
|
|
readonly IUniTaskAsyncEnumerable<T5> source5;
|
|
readonly IUniTaskAsyncEnumerable<T6> source6;
|
|
readonly IUniTaskAsyncEnumerable<T7> source7;
|
|
readonly IUniTaskAsyncEnumerable<T8> source8;
|
|
|
|
readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, TResult> resultSelector;
|
|
|
|
public CombineLatest(IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, IUniTaskAsyncEnumerable<T7> source7, IUniTaskAsyncEnumerable<T8> source8, Func<T1, T2, T3, T4, T5, T6, T7, T8, TResult> resultSelector)
|
|
{
|
|
this.source1 = source1;
|
|
this.source2 = source2;
|
|
this.source3 = source3;
|
|
this.source4 = source4;
|
|
this.source5 = source5;
|
|
this.source6 = source6;
|
|
this.source7 = source7;
|
|
this.source8 = source8;
|
|
|
|
this.resultSelector = resultSelector;
|
|
}
|
|
|
|
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
|
{
|
|
return new _CombineLatest(source1, source2, source3, source4, source5, source6, source7, source8, resultSelector, cancellationToken);
|
|
}
|
|
|
|
class _CombineLatest : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
|
|
{
|
|
static readonly Action<object> Completed1Delegate = Completed1;
|
|
static readonly Action<object> Completed2Delegate = Completed2;
|
|
static readonly Action<object> Completed3Delegate = Completed3;
|
|
static readonly Action<object> Completed4Delegate = Completed4;
|
|
static readonly Action<object> Completed5Delegate = Completed5;
|
|
static readonly Action<object> Completed6Delegate = Completed6;
|
|
static readonly Action<object> Completed7Delegate = Completed7;
|
|
static readonly Action<object> Completed8Delegate = Completed8;
|
|
const int CompleteCount = 8;
|
|
|
|
readonly IUniTaskAsyncEnumerable<T1> source1;
|
|
readonly IUniTaskAsyncEnumerable<T2> source2;
|
|
readonly IUniTaskAsyncEnumerable<T3> source3;
|
|
readonly IUniTaskAsyncEnumerable<T4> source4;
|
|
readonly IUniTaskAsyncEnumerable<T5> source5;
|
|
readonly IUniTaskAsyncEnumerable<T6> source6;
|
|
readonly IUniTaskAsyncEnumerable<T7> source7;
|
|
readonly IUniTaskAsyncEnumerable<T8> source8;
|
|
|
|
readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, TResult> resultSelector;
|
|
CancellationToken cancellationToken;
|
|
|
|
IUniTaskAsyncEnumerator<T1> enumerator1;
|
|
UniTask<bool>.Awaiter awaiter1;
|
|
bool hasCurrent1;
|
|
bool running1;
|
|
T1 current1;
|
|
|
|
IUniTaskAsyncEnumerator<T2> enumerator2;
|
|
UniTask<bool>.Awaiter awaiter2;
|
|
bool hasCurrent2;
|
|
bool running2;
|
|
T2 current2;
|
|
|
|
IUniTaskAsyncEnumerator<T3> enumerator3;
|
|
UniTask<bool>.Awaiter awaiter3;
|
|
bool hasCurrent3;
|
|
bool running3;
|
|
T3 current3;
|
|
|
|
IUniTaskAsyncEnumerator<T4> enumerator4;
|
|
UniTask<bool>.Awaiter awaiter4;
|
|
bool hasCurrent4;
|
|
bool running4;
|
|
T4 current4;
|
|
|
|
IUniTaskAsyncEnumerator<T5> enumerator5;
|
|
UniTask<bool>.Awaiter awaiter5;
|
|
bool hasCurrent5;
|
|
bool running5;
|
|
T5 current5;
|
|
|
|
IUniTaskAsyncEnumerator<T6> enumerator6;
|
|
UniTask<bool>.Awaiter awaiter6;
|
|
bool hasCurrent6;
|
|
bool running6;
|
|
T6 current6;
|
|
|
|
IUniTaskAsyncEnumerator<T7> enumerator7;
|
|
UniTask<bool>.Awaiter awaiter7;
|
|
bool hasCurrent7;
|
|
bool running7;
|
|
T7 current7;
|
|
|
|
IUniTaskAsyncEnumerator<T8> enumerator8;
|
|
UniTask<bool>.Awaiter awaiter8;
|
|
bool hasCurrent8;
|
|
bool running8;
|
|
T8 current8;
|
|
|
|
int completedCount;
|
|
bool syncRunning;
|
|
TResult result;
|
|
|
|
public _CombineLatest(IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, IUniTaskAsyncEnumerable<T7> source7, IUniTaskAsyncEnumerable<T8> source8, Func<T1, T2, T3, T4, T5, T6, T7, T8, TResult> resultSelector, CancellationToken cancellationToken)
|
|
{
|
|
this.source1 = source1;
|
|
this.source2 = source2;
|
|
this.source3 = source3;
|
|
this.source4 = source4;
|
|
this.source5 = source5;
|
|
this.source6 = source6;
|
|
this.source7 = source7;
|
|
this.source8 = source8;
|
|
|
|
this.resultSelector = resultSelector;
|
|
this.cancellationToken = cancellationToken;
|
|
TaskTracker.TrackActiveTask(this, 3);
|
|
}
|
|
|
|
public TResult Current => result;
|
|
|
|
public UniTask<bool> MoveNextAsync()
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
if (completedCount == CompleteCount) return CompletedTasks.False;
|
|
|
|
if (enumerator1 == null)
|
|
{
|
|
enumerator1 = source1.GetAsyncEnumerator(cancellationToken);
|
|
enumerator2 = source2.GetAsyncEnumerator(cancellationToken);
|
|
enumerator3 = source3.GetAsyncEnumerator(cancellationToken);
|
|
enumerator4 = source4.GetAsyncEnumerator(cancellationToken);
|
|
enumerator5 = source5.GetAsyncEnumerator(cancellationToken);
|
|
enumerator6 = source6.GetAsyncEnumerator(cancellationToken);
|
|
enumerator7 = source7.GetAsyncEnumerator(cancellationToken);
|
|
enumerator8 = source8.GetAsyncEnumerator(cancellationToken);
|
|
}
|
|
|
|
completionSource.Reset();
|
|
|
|
AGAIN:
|
|
syncRunning = true;
|
|
if (!running1)
|
|
{
|
|
running1 = true;
|
|
awaiter1 = enumerator1.MoveNextAsync().GetAwaiter();
|
|
if (awaiter1.IsCompleted)
|
|
{
|
|
Completed1(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter1.SourceOnCompleted(Completed1Delegate, this);
|
|
}
|
|
}
|
|
if (!running2)
|
|
{
|
|
running2 = true;
|
|
awaiter2 = enumerator2.MoveNextAsync().GetAwaiter();
|
|
if (awaiter2.IsCompleted)
|
|
{
|
|
Completed2(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter2.SourceOnCompleted(Completed2Delegate, this);
|
|
}
|
|
}
|
|
if (!running3)
|
|
{
|
|
running3 = true;
|
|
awaiter3 = enumerator3.MoveNextAsync().GetAwaiter();
|
|
if (awaiter3.IsCompleted)
|
|
{
|
|
Completed3(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter3.SourceOnCompleted(Completed3Delegate, this);
|
|
}
|
|
}
|
|
if (!running4)
|
|
{
|
|
running4 = true;
|
|
awaiter4 = enumerator4.MoveNextAsync().GetAwaiter();
|
|
if (awaiter4.IsCompleted)
|
|
{
|
|
Completed4(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter4.SourceOnCompleted(Completed4Delegate, this);
|
|
}
|
|
}
|
|
if (!running5)
|
|
{
|
|
running5 = true;
|
|
awaiter5 = enumerator5.MoveNextAsync().GetAwaiter();
|
|
if (awaiter5.IsCompleted)
|
|
{
|
|
Completed5(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter5.SourceOnCompleted(Completed5Delegate, this);
|
|
}
|
|
}
|
|
if (!running6)
|
|
{
|
|
running6 = true;
|
|
awaiter6 = enumerator6.MoveNextAsync().GetAwaiter();
|
|
if (awaiter6.IsCompleted)
|
|
{
|
|
Completed6(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter6.SourceOnCompleted(Completed6Delegate, this);
|
|
}
|
|
}
|
|
if (!running7)
|
|
{
|
|
running7 = true;
|
|
awaiter7 = enumerator7.MoveNextAsync().GetAwaiter();
|
|
if (awaiter7.IsCompleted)
|
|
{
|
|
Completed7(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter7.SourceOnCompleted(Completed7Delegate, this);
|
|
}
|
|
}
|
|
if (!running8)
|
|
{
|
|
running8 = true;
|
|
awaiter8 = enumerator8.MoveNextAsync().GetAwaiter();
|
|
if (awaiter8.IsCompleted)
|
|
{
|
|
Completed8(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter8.SourceOnCompleted(Completed8Delegate, this);
|
|
}
|
|
}
|
|
|
|
if (!running1 || !running2 || !running3 || !running4 || !running5 || !running6 || !running7 || !running8)
|
|
{
|
|
goto AGAIN;
|
|
}
|
|
syncRunning = false;
|
|
|
|
return new UniTask<bool>(this, completionSource.Version);
|
|
}
|
|
|
|
static void Completed1(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running1 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter1.GetResult())
|
|
{
|
|
self.hasCurrent1 = true;
|
|
self.current1 = self.enumerator1.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter1 = self.enumerator1.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter1.SourceOnCompleted(Completed1Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed2(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running2 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter2.GetResult())
|
|
{
|
|
self.hasCurrent2 = true;
|
|
self.current2 = self.enumerator2.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter2 = self.enumerator2.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter2.SourceOnCompleted(Completed2Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed3(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running3 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter3.GetResult())
|
|
{
|
|
self.hasCurrent3 = true;
|
|
self.current3 = self.enumerator3.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter3 = self.enumerator3.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter3.SourceOnCompleted(Completed3Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed4(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running4 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter4.GetResult())
|
|
{
|
|
self.hasCurrent4 = true;
|
|
self.current4 = self.enumerator4.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter4 = self.enumerator4.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter4.SourceOnCompleted(Completed4Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed5(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running5 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter5.GetResult())
|
|
{
|
|
self.hasCurrent5 = true;
|
|
self.current5 = self.enumerator5.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter5 = self.enumerator5.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter5.SourceOnCompleted(Completed5Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed6(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running6 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter6.GetResult())
|
|
{
|
|
self.hasCurrent6 = true;
|
|
self.current6 = self.enumerator6.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter6 = self.enumerator6.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter6.SourceOnCompleted(Completed6Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed7(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running7 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter7.GetResult())
|
|
{
|
|
self.hasCurrent7 = true;
|
|
self.current7 = self.enumerator7.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running7 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running7 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running7 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter7 = self.enumerator7.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter7.SourceOnCompleted(Completed7Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed8(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running8 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter8.GetResult())
|
|
{
|
|
self.hasCurrent8 = true;
|
|
self.current8 = self.enumerator8.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running8 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running8 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running8 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter8 = self.enumerator8.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter8.SourceOnCompleted(Completed8Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
bool TrySetResult()
|
|
{
|
|
if (hasCurrent1 && hasCurrent2 && hasCurrent3 && hasCurrent4 && hasCurrent5 && hasCurrent6 && hasCurrent7 && hasCurrent8)
|
|
{
|
|
result = resultSelector(current1, current2, current3, current4, current5, current6, current7, current8);
|
|
completionSource.TrySetResult(true);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async UniTask DisposeAsync()
|
|
{
|
|
TaskTracker.RemoveTracking(this);
|
|
if (enumerator1 != null)
|
|
{
|
|
await enumerator1.DisposeAsync();
|
|
}
|
|
if (enumerator2 != null)
|
|
{
|
|
await enumerator2.DisposeAsync();
|
|
}
|
|
if (enumerator3 != null)
|
|
{
|
|
await enumerator3.DisposeAsync();
|
|
}
|
|
if (enumerator4 != null)
|
|
{
|
|
await enumerator4.DisposeAsync();
|
|
}
|
|
if (enumerator5 != null)
|
|
{
|
|
await enumerator5.DisposeAsync();
|
|
}
|
|
if (enumerator6 != null)
|
|
{
|
|
await enumerator6.DisposeAsync();
|
|
}
|
|
if (enumerator7 != null)
|
|
{
|
|
await enumerator7.DisposeAsync();
|
|
}
|
|
if (enumerator8 != null)
|
|
{
|
|
await enumerator8.DisposeAsync();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
internal class CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> : IUniTaskAsyncEnumerable<TResult>
|
|
{
|
|
readonly IUniTaskAsyncEnumerable<T1> source1;
|
|
readonly IUniTaskAsyncEnumerable<T2> source2;
|
|
readonly IUniTaskAsyncEnumerable<T3> source3;
|
|
readonly IUniTaskAsyncEnumerable<T4> source4;
|
|
readonly IUniTaskAsyncEnumerable<T5> source5;
|
|
readonly IUniTaskAsyncEnumerable<T6> source6;
|
|
readonly IUniTaskAsyncEnumerable<T7> source7;
|
|
readonly IUniTaskAsyncEnumerable<T8> source8;
|
|
readonly IUniTaskAsyncEnumerable<T9> source9;
|
|
|
|
readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> resultSelector;
|
|
|
|
public CombineLatest(IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, IUniTaskAsyncEnumerable<T7> source7, IUniTaskAsyncEnumerable<T8> source8, IUniTaskAsyncEnumerable<T9> source9, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> resultSelector)
|
|
{
|
|
this.source1 = source1;
|
|
this.source2 = source2;
|
|
this.source3 = source3;
|
|
this.source4 = source4;
|
|
this.source5 = source5;
|
|
this.source6 = source6;
|
|
this.source7 = source7;
|
|
this.source8 = source8;
|
|
this.source9 = source9;
|
|
|
|
this.resultSelector = resultSelector;
|
|
}
|
|
|
|
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
|
{
|
|
return new _CombineLatest(source1, source2, source3, source4, source5, source6, source7, source8, source9, resultSelector, cancellationToken);
|
|
}
|
|
|
|
class _CombineLatest : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
|
|
{
|
|
static readonly Action<object> Completed1Delegate = Completed1;
|
|
static readonly Action<object> Completed2Delegate = Completed2;
|
|
static readonly Action<object> Completed3Delegate = Completed3;
|
|
static readonly Action<object> Completed4Delegate = Completed4;
|
|
static readonly Action<object> Completed5Delegate = Completed5;
|
|
static readonly Action<object> Completed6Delegate = Completed6;
|
|
static readonly Action<object> Completed7Delegate = Completed7;
|
|
static readonly Action<object> Completed8Delegate = Completed8;
|
|
static readonly Action<object> Completed9Delegate = Completed9;
|
|
const int CompleteCount = 9;
|
|
|
|
readonly IUniTaskAsyncEnumerable<T1> source1;
|
|
readonly IUniTaskAsyncEnumerable<T2> source2;
|
|
readonly IUniTaskAsyncEnumerable<T3> source3;
|
|
readonly IUniTaskAsyncEnumerable<T4> source4;
|
|
readonly IUniTaskAsyncEnumerable<T5> source5;
|
|
readonly IUniTaskAsyncEnumerable<T6> source6;
|
|
readonly IUniTaskAsyncEnumerable<T7> source7;
|
|
readonly IUniTaskAsyncEnumerable<T8> source8;
|
|
readonly IUniTaskAsyncEnumerable<T9> source9;
|
|
|
|
readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> resultSelector;
|
|
CancellationToken cancellationToken;
|
|
|
|
IUniTaskAsyncEnumerator<T1> enumerator1;
|
|
UniTask<bool>.Awaiter awaiter1;
|
|
bool hasCurrent1;
|
|
bool running1;
|
|
T1 current1;
|
|
|
|
IUniTaskAsyncEnumerator<T2> enumerator2;
|
|
UniTask<bool>.Awaiter awaiter2;
|
|
bool hasCurrent2;
|
|
bool running2;
|
|
T2 current2;
|
|
|
|
IUniTaskAsyncEnumerator<T3> enumerator3;
|
|
UniTask<bool>.Awaiter awaiter3;
|
|
bool hasCurrent3;
|
|
bool running3;
|
|
T3 current3;
|
|
|
|
IUniTaskAsyncEnumerator<T4> enumerator4;
|
|
UniTask<bool>.Awaiter awaiter4;
|
|
bool hasCurrent4;
|
|
bool running4;
|
|
T4 current4;
|
|
|
|
IUniTaskAsyncEnumerator<T5> enumerator5;
|
|
UniTask<bool>.Awaiter awaiter5;
|
|
bool hasCurrent5;
|
|
bool running5;
|
|
T5 current5;
|
|
|
|
IUniTaskAsyncEnumerator<T6> enumerator6;
|
|
UniTask<bool>.Awaiter awaiter6;
|
|
bool hasCurrent6;
|
|
bool running6;
|
|
T6 current6;
|
|
|
|
IUniTaskAsyncEnumerator<T7> enumerator7;
|
|
UniTask<bool>.Awaiter awaiter7;
|
|
bool hasCurrent7;
|
|
bool running7;
|
|
T7 current7;
|
|
|
|
IUniTaskAsyncEnumerator<T8> enumerator8;
|
|
UniTask<bool>.Awaiter awaiter8;
|
|
bool hasCurrent8;
|
|
bool running8;
|
|
T8 current8;
|
|
|
|
IUniTaskAsyncEnumerator<T9> enumerator9;
|
|
UniTask<bool>.Awaiter awaiter9;
|
|
bool hasCurrent9;
|
|
bool running9;
|
|
T9 current9;
|
|
|
|
int completedCount;
|
|
bool syncRunning;
|
|
TResult result;
|
|
|
|
public _CombineLatest(IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, IUniTaskAsyncEnumerable<T7> source7, IUniTaskAsyncEnumerable<T8> source8, IUniTaskAsyncEnumerable<T9> source9, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> resultSelector, CancellationToken cancellationToken)
|
|
{
|
|
this.source1 = source1;
|
|
this.source2 = source2;
|
|
this.source3 = source3;
|
|
this.source4 = source4;
|
|
this.source5 = source5;
|
|
this.source6 = source6;
|
|
this.source7 = source7;
|
|
this.source8 = source8;
|
|
this.source9 = source9;
|
|
|
|
this.resultSelector = resultSelector;
|
|
this.cancellationToken = cancellationToken;
|
|
TaskTracker.TrackActiveTask(this, 3);
|
|
}
|
|
|
|
public TResult Current => result;
|
|
|
|
public UniTask<bool> MoveNextAsync()
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
if (completedCount == CompleteCount) return CompletedTasks.False;
|
|
|
|
if (enumerator1 == null)
|
|
{
|
|
enumerator1 = source1.GetAsyncEnumerator(cancellationToken);
|
|
enumerator2 = source2.GetAsyncEnumerator(cancellationToken);
|
|
enumerator3 = source3.GetAsyncEnumerator(cancellationToken);
|
|
enumerator4 = source4.GetAsyncEnumerator(cancellationToken);
|
|
enumerator5 = source5.GetAsyncEnumerator(cancellationToken);
|
|
enumerator6 = source6.GetAsyncEnumerator(cancellationToken);
|
|
enumerator7 = source7.GetAsyncEnumerator(cancellationToken);
|
|
enumerator8 = source8.GetAsyncEnumerator(cancellationToken);
|
|
enumerator9 = source9.GetAsyncEnumerator(cancellationToken);
|
|
}
|
|
|
|
completionSource.Reset();
|
|
|
|
AGAIN:
|
|
syncRunning = true;
|
|
if (!running1)
|
|
{
|
|
running1 = true;
|
|
awaiter1 = enumerator1.MoveNextAsync().GetAwaiter();
|
|
if (awaiter1.IsCompleted)
|
|
{
|
|
Completed1(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter1.SourceOnCompleted(Completed1Delegate, this);
|
|
}
|
|
}
|
|
if (!running2)
|
|
{
|
|
running2 = true;
|
|
awaiter2 = enumerator2.MoveNextAsync().GetAwaiter();
|
|
if (awaiter2.IsCompleted)
|
|
{
|
|
Completed2(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter2.SourceOnCompleted(Completed2Delegate, this);
|
|
}
|
|
}
|
|
if (!running3)
|
|
{
|
|
running3 = true;
|
|
awaiter3 = enumerator3.MoveNextAsync().GetAwaiter();
|
|
if (awaiter3.IsCompleted)
|
|
{
|
|
Completed3(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter3.SourceOnCompleted(Completed3Delegate, this);
|
|
}
|
|
}
|
|
if (!running4)
|
|
{
|
|
running4 = true;
|
|
awaiter4 = enumerator4.MoveNextAsync().GetAwaiter();
|
|
if (awaiter4.IsCompleted)
|
|
{
|
|
Completed4(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter4.SourceOnCompleted(Completed4Delegate, this);
|
|
}
|
|
}
|
|
if (!running5)
|
|
{
|
|
running5 = true;
|
|
awaiter5 = enumerator5.MoveNextAsync().GetAwaiter();
|
|
if (awaiter5.IsCompleted)
|
|
{
|
|
Completed5(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter5.SourceOnCompleted(Completed5Delegate, this);
|
|
}
|
|
}
|
|
if (!running6)
|
|
{
|
|
running6 = true;
|
|
awaiter6 = enumerator6.MoveNextAsync().GetAwaiter();
|
|
if (awaiter6.IsCompleted)
|
|
{
|
|
Completed6(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter6.SourceOnCompleted(Completed6Delegate, this);
|
|
}
|
|
}
|
|
if (!running7)
|
|
{
|
|
running7 = true;
|
|
awaiter7 = enumerator7.MoveNextAsync().GetAwaiter();
|
|
if (awaiter7.IsCompleted)
|
|
{
|
|
Completed7(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter7.SourceOnCompleted(Completed7Delegate, this);
|
|
}
|
|
}
|
|
if (!running8)
|
|
{
|
|
running8 = true;
|
|
awaiter8 = enumerator8.MoveNextAsync().GetAwaiter();
|
|
if (awaiter8.IsCompleted)
|
|
{
|
|
Completed8(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter8.SourceOnCompleted(Completed8Delegate, this);
|
|
}
|
|
}
|
|
if (!running9)
|
|
{
|
|
running9 = true;
|
|
awaiter9 = enumerator9.MoveNextAsync().GetAwaiter();
|
|
if (awaiter9.IsCompleted)
|
|
{
|
|
Completed9(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter9.SourceOnCompleted(Completed9Delegate, this);
|
|
}
|
|
}
|
|
|
|
if (!running1 || !running2 || !running3 || !running4 || !running5 || !running6 || !running7 || !running8 || !running9)
|
|
{
|
|
goto AGAIN;
|
|
}
|
|
syncRunning = false;
|
|
|
|
return new UniTask<bool>(this, completionSource.Version);
|
|
}
|
|
|
|
static void Completed1(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running1 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter1.GetResult())
|
|
{
|
|
self.hasCurrent1 = true;
|
|
self.current1 = self.enumerator1.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter1 = self.enumerator1.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter1.SourceOnCompleted(Completed1Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed2(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running2 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter2.GetResult())
|
|
{
|
|
self.hasCurrent2 = true;
|
|
self.current2 = self.enumerator2.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter2 = self.enumerator2.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter2.SourceOnCompleted(Completed2Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed3(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running3 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter3.GetResult())
|
|
{
|
|
self.hasCurrent3 = true;
|
|
self.current3 = self.enumerator3.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter3 = self.enumerator3.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter3.SourceOnCompleted(Completed3Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed4(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running4 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter4.GetResult())
|
|
{
|
|
self.hasCurrent4 = true;
|
|
self.current4 = self.enumerator4.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter4 = self.enumerator4.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter4.SourceOnCompleted(Completed4Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed5(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running5 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter5.GetResult())
|
|
{
|
|
self.hasCurrent5 = true;
|
|
self.current5 = self.enumerator5.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter5 = self.enumerator5.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter5.SourceOnCompleted(Completed5Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed6(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running6 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter6.GetResult())
|
|
{
|
|
self.hasCurrent6 = true;
|
|
self.current6 = self.enumerator6.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter6 = self.enumerator6.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter6.SourceOnCompleted(Completed6Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed7(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running7 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter7.GetResult())
|
|
{
|
|
self.hasCurrent7 = true;
|
|
self.current7 = self.enumerator7.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running7 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running7 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running7 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter7 = self.enumerator7.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter7.SourceOnCompleted(Completed7Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed8(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running8 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter8.GetResult())
|
|
{
|
|
self.hasCurrent8 = true;
|
|
self.current8 = self.enumerator8.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running8 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running8 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running8 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter8 = self.enumerator8.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter8.SourceOnCompleted(Completed8Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed9(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running9 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter9.GetResult())
|
|
{
|
|
self.hasCurrent9 = true;
|
|
self.current9 = self.enumerator9.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running9 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running9 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running9 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter9 = self.enumerator9.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter9.SourceOnCompleted(Completed9Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
bool TrySetResult()
|
|
{
|
|
if (hasCurrent1 && hasCurrent2 && hasCurrent3 && hasCurrent4 && hasCurrent5 && hasCurrent6 && hasCurrent7 && hasCurrent8 && hasCurrent9)
|
|
{
|
|
result = resultSelector(current1, current2, current3, current4, current5, current6, current7, current8, current9);
|
|
completionSource.TrySetResult(true);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async UniTask DisposeAsync()
|
|
{
|
|
TaskTracker.RemoveTracking(this);
|
|
if (enumerator1 != null)
|
|
{
|
|
await enumerator1.DisposeAsync();
|
|
}
|
|
if (enumerator2 != null)
|
|
{
|
|
await enumerator2.DisposeAsync();
|
|
}
|
|
if (enumerator3 != null)
|
|
{
|
|
await enumerator3.DisposeAsync();
|
|
}
|
|
if (enumerator4 != null)
|
|
{
|
|
await enumerator4.DisposeAsync();
|
|
}
|
|
if (enumerator5 != null)
|
|
{
|
|
await enumerator5.DisposeAsync();
|
|
}
|
|
if (enumerator6 != null)
|
|
{
|
|
await enumerator6.DisposeAsync();
|
|
}
|
|
if (enumerator7 != null)
|
|
{
|
|
await enumerator7.DisposeAsync();
|
|
}
|
|
if (enumerator8 != null)
|
|
{
|
|
await enumerator8.DisposeAsync();
|
|
}
|
|
if (enumerator9 != null)
|
|
{
|
|
await enumerator9.DisposeAsync();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
internal class CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> : IUniTaskAsyncEnumerable<TResult>
|
|
{
|
|
readonly IUniTaskAsyncEnumerable<T1> source1;
|
|
readonly IUniTaskAsyncEnumerable<T2> source2;
|
|
readonly IUniTaskAsyncEnumerable<T3> source3;
|
|
readonly IUniTaskAsyncEnumerable<T4> source4;
|
|
readonly IUniTaskAsyncEnumerable<T5> source5;
|
|
readonly IUniTaskAsyncEnumerable<T6> source6;
|
|
readonly IUniTaskAsyncEnumerable<T7> source7;
|
|
readonly IUniTaskAsyncEnumerable<T8> source8;
|
|
readonly IUniTaskAsyncEnumerable<T9> source9;
|
|
readonly IUniTaskAsyncEnumerable<T10> source10;
|
|
|
|
readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> resultSelector;
|
|
|
|
public CombineLatest(IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, IUniTaskAsyncEnumerable<T7> source7, IUniTaskAsyncEnumerable<T8> source8, IUniTaskAsyncEnumerable<T9> source9, IUniTaskAsyncEnumerable<T10> source10, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> resultSelector)
|
|
{
|
|
this.source1 = source1;
|
|
this.source2 = source2;
|
|
this.source3 = source3;
|
|
this.source4 = source4;
|
|
this.source5 = source5;
|
|
this.source6 = source6;
|
|
this.source7 = source7;
|
|
this.source8 = source8;
|
|
this.source9 = source9;
|
|
this.source10 = source10;
|
|
|
|
this.resultSelector = resultSelector;
|
|
}
|
|
|
|
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
|
{
|
|
return new _CombineLatest(source1, source2, source3, source4, source5, source6, source7, source8, source9, source10, resultSelector, cancellationToken);
|
|
}
|
|
|
|
class _CombineLatest : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
|
|
{
|
|
static readonly Action<object> Completed1Delegate = Completed1;
|
|
static readonly Action<object> Completed2Delegate = Completed2;
|
|
static readonly Action<object> Completed3Delegate = Completed3;
|
|
static readonly Action<object> Completed4Delegate = Completed4;
|
|
static readonly Action<object> Completed5Delegate = Completed5;
|
|
static readonly Action<object> Completed6Delegate = Completed6;
|
|
static readonly Action<object> Completed7Delegate = Completed7;
|
|
static readonly Action<object> Completed8Delegate = Completed8;
|
|
static readonly Action<object> Completed9Delegate = Completed9;
|
|
static readonly Action<object> Completed10Delegate = Completed10;
|
|
const int CompleteCount = 10;
|
|
|
|
readonly IUniTaskAsyncEnumerable<T1> source1;
|
|
readonly IUniTaskAsyncEnumerable<T2> source2;
|
|
readonly IUniTaskAsyncEnumerable<T3> source3;
|
|
readonly IUniTaskAsyncEnumerable<T4> source4;
|
|
readonly IUniTaskAsyncEnumerable<T5> source5;
|
|
readonly IUniTaskAsyncEnumerable<T6> source6;
|
|
readonly IUniTaskAsyncEnumerable<T7> source7;
|
|
readonly IUniTaskAsyncEnumerable<T8> source8;
|
|
readonly IUniTaskAsyncEnumerable<T9> source9;
|
|
readonly IUniTaskAsyncEnumerable<T10> source10;
|
|
|
|
readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> resultSelector;
|
|
CancellationToken cancellationToken;
|
|
|
|
IUniTaskAsyncEnumerator<T1> enumerator1;
|
|
UniTask<bool>.Awaiter awaiter1;
|
|
bool hasCurrent1;
|
|
bool running1;
|
|
T1 current1;
|
|
|
|
IUniTaskAsyncEnumerator<T2> enumerator2;
|
|
UniTask<bool>.Awaiter awaiter2;
|
|
bool hasCurrent2;
|
|
bool running2;
|
|
T2 current2;
|
|
|
|
IUniTaskAsyncEnumerator<T3> enumerator3;
|
|
UniTask<bool>.Awaiter awaiter3;
|
|
bool hasCurrent3;
|
|
bool running3;
|
|
T3 current3;
|
|
|
|
IUniTaskAsyncEnumerator<T4> enumerator4;
|
|
UniTask<bool>.Awaiter awaiter4;
|
|
bool hasCurrent4;
|
|
bool running4;
|
|
T4 current4;
|
|
|
|
IUniTaskAsyncEnumerator<T5> enumerator5;
|
|
UniTask<bool>.Awaiter awaiter5;
|
|
bool hasCurrent5;
|
|
bool running5;
|
|
T5 current5;
|
|
|
|
IUniTaskAsyncEnumerator<T6> enumerator6;
|
|
UniTask<bool>.Awaiter awaiter6;
|
|
bool hasCurrent6;
|
|
bool running6;
|
|
T6 current6;
|
|
|
|
IUniTaskAsyncEnumerator<T7> enumerator7;
|
|
UniTask<bool>.Awaiter awaiter7;
|
|
bool hasCurrent7;
|
|
bool running7;
|
|
T7 current7;
|
|
|
|
IUniTaskAsyncEnumerator<T8> enumerator8;
|
|
UniTask<bool>.Awaiter awaiter8;
|
|
bool hasCurrent8;
|
|
bool running8;
|
|
T8 current8;
|
|
|
|
IUniTaskAsyncEnumerator<T9> enumerator9;
|
|
UniTask<bool>.Awaiter awaiter9;
|
|
bool hasCurrent9;
|
|
bool running9;
|
|
T9 current9;
|
|
|
|
IUniTaskAsyncEnumerator<T10> enumerator10;
|
|
UniTask<bool>.Awaiter awaiter10;
|
|
bool hasCurrent10;
|
|
bool running10;
|
|
T10 current10;
|
|
|
|
int completedCount;
|
|
bool syncRunning;
|
|
TResult result;
|
|
|
|
public _CombineLatest(IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, IUniTaskAsyncEnumerable<T7> source7, IUniTaskAsyncEnumerable<T8> source8, IUniTaskAsyncEnumerable<T9> source9, IUniTaskAsyncEnumerable<T10> source10, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> resultSelector, CancellationToken cancellationToken)
|
|
{
|
|
this.source1 = source1;
|
|
this.source2 = source2;
|
|
this.source3 = source3;
|
|
this.source4 = source4;
|
|
this.source5 = source5;
|
|
this.source6 = source6;
|
|
this.source7 = source7;
|
|
this.source8 = source8;
|
|
this.source9 = source9;
|
|
this.source10 = source10;
|
|
|
|
this.resultSelector = resultSelector;
|
|
this.cancellationToken = cancellationToken;
|
|
TaskTracker.TrackActiveTask(this, 3);
|
|
}
|
|
|
|
public TResult Current => result;
|
|
|
|
public UniTask<bool> MoveNextAsync()
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
if (completedCount == CompleteCount) return CompletedTasks.False;
|
|
|
|
if (enumerator1 == null)
|
|
{
|
|
enumerator1 = source1.GetAsyncEnumerator(cancellationToken);
|
|
enumerator2 = source2.GetAsyncEnumerator(cancellationToken);
|
|
enumerator3 = source3.GetAsyncEnumerator(cancellationToken);
|
|
enumerator4 = source4.GetAsyncEnumerator(cancellationToken);
|
|
enumerator5 = source5.GetAsyncEnumerator(cancellationToken);
|
|
enumerator6 = source6.GetAsyncEnumerator(cancellationToken);
|
|
enumerator7 = source7.GetAsyncEnumerator(cancellationToken);
|
|
enumerator8 = source8.GetAsyncEnumerator(cancellationToken);
|
|
enumerator9 = source9.GetAsyncEnumerator(cancellationToken);
|
|
enumerator10 = source10.GetAsyncEnumerator(cancellationToken);
|
|
}
|
|
|
|
completionSource.Reset();
|
|
|
|
AGAIN:
|
|
syncRunning = true;
|
|
if (!running1)
|
|
{
|
|
running1 = true;
|
|
awaiter1 = enumerator1.MoveNextAsync().GetAwaiter();
|
|
if (awaiter1.IsCompleted)
|
|
{
|
|
Completed1(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter1.SourceOnCompleted(Completed1Delegate, this);
|
|
}
|
|
}
|
|
if (!running2)
|
|
{
|
|
running2 = true;
|
|
awaiter2 = enumerator2.MoveNextAsync().GetAwaiter();
|
|
if (awaiter2.IsCompleted)
|
|
{
|
|
Completed2(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter2.SourceOnCompleted(Completed2Delegate, this);
|
|
}
|
|
}
|
|
if (!running3)
|
|
{
|
|
running3 = true;
|
|
awaiter3 = enumerator3.MoveNextAsync().GetAwaiter();
|
|
if (awaiter3.IsCompleted)
|
|
{
|
|
Completed3(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter3.SourceOnCompleted(Completed3Delegate, this);
|
|
}
|
|
}
|
|
if (!running4)
|
|
{
|
|
running4 = true;
|
|
awaiter4 = enumerator4.MoveNextAsync().GetAwaiter();
|
|
if (awaiter4.IsCompleted)
|
|
{
|
|
Completed4(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter4.SourceOnCompleted(Completed4Delegate, this);
|
|
}
|
|
}
|
|
if (!running5)
|
|
{
|
|
running5 = true;
|
|
awaiter5 = enumerator5.MoveNextAsync().GetAwaiter();
|
|
if (awaiter5.IsCompleted)
|
|
{
|
|
Completed5(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter5.SourceOnCompleted(Completed5Delegate, this);
|
|
}
|
|
}
|
|
if (!running6)
|
|
{
|
|
running6 = true;
|
|
awaiter6 = enumerator6.MoveNextAsync().GetAwaiter();
|
|
if (awaiter6.IsCompleted)
|
|
{
|
|
Completed6(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter6.SourceOnCompleted(Completed6Delegate, this);
|
|
}
|
|
}
|
|
if (!running7)
|
|
{
|
|
running7 = true;
|
|
awaiter7 = enumerator7.MoveNextAsync().GetAwaiter();
|
|
if (awaiter7.IsCompleted)
|
|
{
|
|
Completed7(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter7.SourceOnCompleted(Completed7Delegate, this);
|
|
}
|
|
}
|
|
if (!running8)
|
|
{
|
|
running8 = true;
|
|
awaiter8 = enumerator8.MoveNextAsync().GetAwaiter();
|
|
if (awaiter8.IsCompleted)
|
|
{
|
|
Completed8(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter8.SourceOnCompleted(Completed8Delegate, this);
|
|
}
|
|
}
|
|
if (!running9)
|
|
{
|
|
running9 = true;
|
|
awaiter9 = enumerator9.MoveNextAsync().GetAwaiter();
|
|
if (awaiter9.IsCompleted)
|
|
{
|
|
Completed9(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter9.SourceOnCompleted(Completed9Delegate, this);
|
|
}
|
|
}
|
|
if (!running10)
|
|
{
|
|
running10 = true;
|
|
awaiter10 = enumerator10.MoveNextAsync().GetAwaiter();
|
|
if (awaiter10.IsCompleted)
|
|
{
|
|
Completed10(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter10.SourceOnCompleted(Completed10Delegate, this);
|
|
}
|
|
}
|
|
|
|
if (!running1 || !running2 || !running3 || !running4 || !running5 || !running6 || !running7 || !running8 || !running9 || !running10)
|
|
{
|
|
goto AGAIN;
|
|
}
|
|
syncRunning = false;
|
|
|
|
return new UniTask<bool>(this, completionSource.Version);
|
|
}
|
|
|
|
static void Completed1(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running1 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter1.GetResult())
|
|
{
|
|
self.hasCurrent1 = true;
|
|
self.current1 = self.enumerator1.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter1 = self.enumerator1.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter1.SourceOnCompleted(Completed1Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed2(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running2 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter2.GetResult())
|
|
{
|
|
self.hasCurrent2 = true;
|
|
self.current2 = self.enumerator2.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter2 = self.enumerator2.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter2.SourceOnCompleted(Completed2Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed3(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running3 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter3.GetResult())
|
|
{
|
|
self.hasCurrent3 = true;
|
|
self.current3 = self.enumerator3.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter3 = self.enumerator3.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter3.SourceOnCompleted(Completed3Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed4(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running4 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter4.GetResult())
|
|
{
|
|
self.hasCurrent4 = true;
|
|
self.current4 = self.enumerator4.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter4 = self.enumerator4.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter4.SourceOnCompleted(Completed4Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed5(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running5 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter5.GetResult())
|
|
{
|
|
self.hasCurrent5 = true;
|
|
self.current5 = self.enumerator5.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter5 = self.enumerator5.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter5.SourceOnCompleted(Completed5Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed6(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running6 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter6.GetResult())
|
|
{
|
|
self.hasCurrent6 = true;
|
|
self.current6 = self.enumerator6.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter6 = self.enumerator6.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter6.SourceOnCompleted(Completed6Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed7(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running7 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter7.GetResult())
|
|
{
|
|
self.hasCurrent7 = true;
|
|
self.current7 = self.enumerator7.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running7 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running7 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running7 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter7 = self.enumerator7.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter7.SourceOnCompleted(Completed7Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed8(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running8 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter8.GetResult())
|
|
{
|
|
self.hasCurrent8 = true;
|
|
self.current8 = self.enumerator8.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running8 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running8 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running8 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter8 = self.enumerator8.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter8.SourceOnCompleted(Completed8Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed9(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running9 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter9.GetResult())
|
|
{
|
|
self.hasCurrent9 = true;
|
|
self.current9 = self.enumerator9.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running9 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running9 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running9 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter9 = self.enumerator9.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter9.SourceOnCompleted(Completed9Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed10(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running10 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter10.GetResult())
|
|
{
|
|
self.hasCurrent10 = true;
|
|
self.current10 = self.enumerator10.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running10 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running10 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running10 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter10 = self.enumerator10.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter10.SourceOnCompleted(Completed10Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
bool TrySetResult()
|
|
{
|
|
if (hasCurrent1 && hasCurrent2 && hasCurrent3 && hasCurrent4 && hasCurrent5 && hasCurrent6 && hasCurrent7 && hasCurrent8 && hasCurrent9 && hasCurrent10)
|
|
{
|
|
result = resultSelector(current1, current2, current3, current4, current5, current6, current7, current8, current9, current10);
|
|
completionSource.TrySetResult(true);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async UniTask DisposeAsync()
|
|
{
|
|
TaskTracker.RemoveTracking(this);
|
|
if (enumerator1 != null)
|
|
{
|
|
await enumerator1.DisposeAsync();
|
|
}
|
|
if (enumerator2 != null)
|
|
{
|
|
await enumerator2.DisposeAsync();
|
|
}
|
|
if (enumerator3 != null)
|
|
{
|
|
await enumerator3.DisposeAsync();
|
|
}
|
|
if (enumerator4 != null)
|
|
{
|
|
await enumerator4.DisposeAsync();
|
|
}
|
|
if (enumerator5 != null)
|
|
{
|
|
await enumerator5.DisposeAsync();
|
|
}
|
|
if (enumerator6 != null)
|
|
{
|
|
await enumerator6.DisposeAsync();
|
|
}
|
|
if (enumerator7 != null)
|
|
{
|
|
await enumerator7.DisposeAsync();
|
|
}
|
|
if (enumerator8 != null)
|
|
{
|
|
await enumerator8.DisposeAsync();
|
|
}
|
|
if (enumerator9 != null)
|
|
{
|
|
await enumerator9.DisposeAsync();
|
|
}
|
|
if (enumerator10 != null)
|
|
{
|
|
await enumerator10.DisposeAsync();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
internal class CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult> : IUniTaskAsyncEnumerable<TResult>
|
|
{
|
|
readonly IUniTaskAsyncEnumerable<T1> source1;
|
|
readonly IUniTaskAsyncEnumerable<T2> source2;
|
|
readonly IUniTaskAsyncEnumerable<T3> source3;
|
|
readonly IUniTaskAsyncEnumerable<T4> source4;
|
|
readonly IUniTaskAsyncEnumerable<T5> source5;
|
|
readonly IUniTaskAsyncEnumerable<T6> source6;
|
|
readonly IUniTaskAsyncEnumerable<T7> source7;
|
|
readonly IUniTaskAsyncEnumerable<T8> source8;
|
|
readonly IUniTaskAsyncEnumerable<T9> source9;
|
|
readonly IUniTaskAsyncEnumerable<T10> source10;
|
|
readonly IUniTaskAsyncEnumerable<T11> source11;
|
|
|
|
readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult> resultSelector;
|
|
|
|
public CombineLatest(IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, IUniTaskAsyncEnumerable<T7> source7, IUniTaskAsyncEnumerable<T8> source8, IUniTaskAsyncEnumerable<T9> source9, IUniTaskAsyncEnumerable<T10> source10, IUniTaskAsyncEnumerable<T11> source11, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult> resultSelector)
|
|
{
|
|
this.source1 = source1;
|
|
this.source2 = source2;
|
|
this.source3 = source3;
|
|
this.source4 = source4;
|
|
this.source5 = source5;
|
|
this.source6 = source6;
|
|
this.source7 = source7;
|
|
this.source8 = source8;
|
|
this.source9 = source9;
|
|
this.source10 = source10;
|
|
this.source11 = source11;
|
|
|
|
this.resultSelector = resultSelector;
|
|
}
|
|
|
|
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
|
{
|
|
return new _CombineLatest(source1, source2, source3, source4, source5, source6, source7, source8, source9, source10, source11, resultSelector, cancellationToken);
|
|
}
|
|
|
|
class _CombineLatest : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
|
|
{
|
|
static readonly Action<object> Completed1Delegate = Completed1;
|
|
static readonly Action<object> Completed2Delegate = Completed2;
|
|
static readonly Action<object> Completed3Delegate = Completed3;
|
|
static readonly Action<object> Completed4Delegate = Completed4;
|
|
static readonly Action<object> Completed5Delegate = Completed5;
|
|
static readonly Action<object> Completed6Delegate = Completed6;
|
|
static readonly Action<object> Completed7Delegate = Completed7;
|
|
static readonly Action<object> Completed8Delegate = Completed8;
|
|
static readonly Action<object> Completed9Delegate = Completed9;
|
|
static readonly Action<object> Completed10Delegate = Completed10;
|
|
static readonly Action<object> Completed11Delegate = Completed11;
|
|
const int CompleteCount = 11;
|
|
|
|
readonly IUniTaskAsyncEnumerable<T1> source1;
|
|
readonly IUniTaskAsyncEnumerable<T2> source2;
|
|
readonly IUniTaskAsyncEnumerable<T3> source3;
|
|
readonly IUniTaskAsyncEnumerable<T4> source4;
|
|
readonly IUniTaskAsyncEnumerable<T5> source5;
|
|
readonly IUniTaskAsyncEnumerable<T6> source6;
|
|
readonly IUniTaskAsyncEnumerable<T7> source7;
|
|
readonly IUniTaskAsyncEnumerable<T8> source8;
|
|
readonly IUniTaskAsyncEnumerable<T9> source9;
|
|
readonly IUniTaskAsyncEnumerable<T10> source10;
|
|
readonly IUniTaskAsyncEnumerable<T11> source11;
|
|
|
|
readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult> resultSelector;
|
|
CancellationToken cancellationToken;
|
|
|
|
IUniTaskAsyncEnumerator<T1> enumerator1;
|
|
UniTask<bool>.Awaiter awaiter1;
|
|
bool hasCurrent1;
|
|
bool running1;
|
|
T1 current1;
|
|
|
|
IUniTaskAsyncEnumerator<T2> enumerator2;
|
|
UniTask<bool>.Awaiter awaiter2;
|
|
bool hasCurrent2;
|
|
bool running2;
|
|
T2 current2;
|
|
|
|
IUniTaskAsyncEnumerator<T3> enumerator3;
|
|
UniTask<bool>.Awaiter awaiter3;
|
|
bool hasCurrent3;
|
|
bool running3;
|
|
T3 current3;
|
|
|
|
IUniTaskAsyncEnumerator<T4> enumerator4;
|
|
UniTask<bool>.Awaiter awaiter4;
|
|
bool hasCurrent4;
|
|
bool running4;
|
|
T4 current4;
|
|
|
|
IUniTaskAsyncEnumerator<T5> enumerator5;
|
|
UniTask<bool>.Awaiter awaiter5;
|
|
bool hasCurrent5;
|
|
bool running5;
|
|
T5 current5;
|
|
|
|
IUniTaskAsyncEnumerator<T6> enumerator6;
|
|
UniTask<bool>.Awaiter awaiter6;
|
|
bool hasCurrent6;
|
|
bool running6;
|
|
T6 current6;
|
|
|
|
IUniTaskAsyncEnumerator<T7> enumerator7;
|
|
UniTask<bool>.Awaiter awaiter7;
|
|
bool hasCurrent7;
|
|
bool running7;
|
|
T7 current7;
|
|
|
|
IUniTaskAsyncEnumerator<T8> enumerator8;
|
|
UniTask<bool>.Awaiter awaiter8;
|
|
bool hasCurrent8;
|
|
bool running8;
|
|
T8 current8;
|
|
|
|
IUniTaskAsyncEnumerator<T9> enumerator9;
|
|
UniTask<bool>.Awaiter awaiter9;
|
|
bool hasCurrent9;
|
|
bool running9;
|
|
T9 current9;
|
|
|
|
IUniTaskAsyncEnumerator<T10> enumerator10;
|
|
UniTask<bool>.Awaiter awaiter10;
|
|
bool hasCurrent10;
|
|
bool running10;
|
|
T10 current10;
|
|
|
|
IUniTaskAsyncEnumerator<T11> enumerator11;
|
|
UniTask<bool>.Awaiter awaiter11;
|
|
bool hasCurrent11;
|
|
bool running11;
|
|
T11 current11;
|
|
|
|
int completedCount;
|
|
bool syncRunning;
|
|
TResult result;
|
|
|
|
public _CombineLatest(IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, IUniTaskAsyncEnumerable<T7> source7, IUniTaskAsyncEnumerable<T8> source8, IUniTaskAsyncEnumerable<T9> source9, IUniTaskAsyncEnumerable<T10> source10, IUniTaskAsyncEnumerable<T11> source11, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TResult> resultSelector, CancellationToken cancellationToken)
|
|
{
|
|
this.source1 = source1;
|
|
this.source2 = source2;
|
|
this.source3 = source3;
|
|
this.source4 = source4;
|
|
this.source5 = source5;
|
|
this.source6 = source6;
|
|
this.source7 = source7;
|
|
this.source8 = source8;
|
|
this.source9 = source9;
|
|
this.source10 = source10;
|
|
this.source11 = source11;
|
|
|
|
this.resultSelector = resultSelector;
|
|
this.cancellationToken = cancellationToken;
|
|
TaskTracker.TrackActiveTask(this, 3);
|
|
}
|
|
|
|
public TResult Current => result;
|
|
|
|
public UniTask<bool> MoveNextAsync()
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
if (completedCount == CompleteCount) return CompletedTasks.False;
|
|
|
|
if (enumerator1 == null)
|
|
{
|
|
enumerator1 = source1.GetAsyncEnumerator(cancellationToken);
|
|
enumerator2 = source2.GetAsyncEnumerator(cancellationToken);
|
|
enumerator3 = source3.GetAsyncEnumerator(cancellationToken);
|
|
enumerator4 = source4.GetAsyncEnumerator(cancellationToken);
|
|
enumerator5 = source5.GetAsyncEnumerator(cancellationToken);
|
|
enumerator6 = source6.GetAsyncEnumerator(cancellationToken);
|
|
enumerator7 = source7.GetAsyncEnumerator(cancellationToken);
|
|
enumerator8 = source8.GetAsyncEnumerator(cancellationToken);
|
|
enumerator9 = source9.GetAsyncEnumerator(cancellationToken);
|
|
enumerator10 = source10.GetAsyncEnumerator(cancellationToken);
|
|
enumerator11 = source11.GetAsyncEnumerator(cancellationToken);
|
|
}
|
|
|
|
completionSource.Reset();
|
|
|
|
AGAIN:
|
|
syncRunning = true;
|
|
if (!running1)
|
|
{
|
|
running1 = true;
|
|
awaiter1 = enumerator1.MoveNextAsync().GetAwaiter();
|
|
if (awaiter1.IsCompleted)
|
|
{
|
|
Completed1(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter1.SourceOnCompleted(Completed1Delegate, this);
|
|
}
|
|
}
|
|
if (!running2)
|
|
{
|
|
running2 = true;
|
|
awaiter2 = enumerator2.MoveNextAsync().GetAwaiter();
|
|
if (awaiter2.IsCompleted)
|
|
{
|
|
Completed2(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter2.SourceOnCompleted(Completed2Delegate, this);
|
|
}
|
|
}
|
|
if (!running3)
|
|
{
|
|
running3 = true;
|
|
awaiter3 = enumerator3.MoveNextAsync().GetAwaiter();
|
|
if (awaiter3.IsCompleted)
|
|
{
|
|
Completed3(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter3.SourceOnCompleted(Completed3Delegate, this);
|
|
}
|
|
}
|
|
if (!running4)
|
|
{
|
|
running4 = true;
|
|
awaiter4 = enumerator4.MoveNextAsync().GetAwaiter();
|
|
if (awaiter4.IsCompleted)
|
|
{
|
|
Completed4(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter4.SourceOnCompleted(Completed4Delegate, this);
|
|
}
|
|
}
|
|
if (!running5)
|
|
{
|
|
running5 = true;
|
|
awaiter5 = enumerator5.MoveNextAsync().GetAwaiter();
|
|
if (awaiter5.IsCompleted)
|
|
{
|
|
Completed5(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter5.SourceOnCompleted(Completed5Delegate, this);
|
|
}
|
|
}
|
|
if (!running6)
|
|
{
|
|
running6 = true;
|
|
awaiter6 = enumerator6.MoveNextAsync().GetAwaiter();
|
|
if (awaiter6.IsCompleted)
|
|
{
|
|
Completed6(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter6.SourceOnCompleted(Completed6Delegate, this);
|
|
}
|
|
}
|
|
if (!running7)
|
|
{
|
|
running7 = true;
|
|
awaiter7 = enumerator7.MoveNextAsync().GetAwaiter();
|
|
if (awaiter7.IsCompleted)
|
|
{
|
|
Completed7(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter7.SourceOnCompleted(Completed7Delegate, this);
|
|
}
|
|
}
|
|
if (!running8)
|
|
{
|
|
running8 = true;
|
|
awaiter8 = enumerator8.MoveNextAsync().GetAwaiter();
|
|
if (awaiter8.IsCompleted)
|
|
{
|
|
Completed8(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter8.SourceOnCompleted(Completed8Delegate, this);
|
|
}
|
|
}
|
|
if (!running9)
|
|
{
|
|
running9 = true;
|
|
awaiter9 = enumerator9.MoveNextAsync().GetAwaiter();
|
|
if (awaiter9.IsCompleted)
|
|
{
|
|
Completed9(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter9.SourceOnCompleted(Completed9Delegate, this);
|
|
}
|
|
}
|
|
if (!running10)
|
|
{
|
|
running10 = true;
|
|
awaiter10 = enumerator10.MoveNextAsync().GetAwaiter();
|
|
if (awaiter10.IsCompleted)
|
|
{
|
|
Completed10(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter10.SourceOnCompleted(Completed10Delegate, this);
|
|
}
|
|
}
|
|
if (!running11)
|
|
{
|
|
running11 = true;
|
|
awaiter11 = enumerator11.MoveNextAsync().GetAwaiter();
|
|
if (awaiter11.IsCompleted)
|
|
{
|
|
Completed11(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter11.SourceOnCompleted(Completed11Delegate, this);
|
|
}
|
|
}
|
|
|
|
if (!running1 || !running2 || !running3 || !running4 || !running5 || !running6 || !running7 || !running8 || !running9 || !running10 || !running11)
|
|
{
|
|
goto AGAIN;
|
|
}
|
|
syncRunning = false;
|
|
|
|
return new UniTask<bool>(this, completionSource.Version);
|
|
}
|
|
|
|
static void Completed1(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running1 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter1.GetResult())
|
|
{
|
|
self.hasCurrent1 = true;
|
|
self.current1 = self.enumerator1.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter1 = self.enumerator1.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter1.SourceOnCompleted(Completed1Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed2(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running2 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter2.GetResult())
|
|
{
|
|
self.hasCurrent2 = true;
|
|
self.current2 = self.enumerator2.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter2 = self.enumerator2.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter2.SourceOnCompleted(Completed2Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed3(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running3 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter3.GetResult())
|
|
{
|
|
self.hasCurrent3 = true;
|
|
self.current3 = self.enumerator3.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter3 = self.enumerator3.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter3.SourceOnCompleted(Completed3Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed4(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running4 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter4.GetResult())
|
|
{
|
|
self.hasCurrent4 = true;
|
|
self.current4 = self.enumerator4.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter4 = self.enumerator4.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter4.SourceOnCompleted(Completed4Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed5(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running5 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter5.GetResult())
|
|
{
|
|
self.hasCurrent5 = true;
|
|
self.current5 = self.enumerator5.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter5 = self.enumerator5.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter5.SourceOnCompleted(Completed5Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed6(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running6 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter6.GetResult())
|
|
{
|
|
self.hasCurrent6 = true;
|
|
self.current6 = self.enumerator6.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter6 = self.enumerator6.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter6.SourceOnCompleted(Completed6Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed7(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running7 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter7.GetResult())
|
|
{
|
|
self.hasCurrent7 = true;
|
|
self.current7 = self.enumerator7.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running7 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running7 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running7 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter7 = self.enumerator7.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter7.SourceOnCompleted(Completed7Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed8(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running8 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter8.GetResult())
|
|
{
|
|
self.hasCurrent8 = true;
|
|
self.current8 = self.enumerator8.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running8 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running8 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running8 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter8 = self.enumerator8.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter8.SourceOnCompleted(Completed8Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed9(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running9 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter9.GetResult())
|
|
{
|
|
self.hasCurrent9 = true;
|
|
self.current9 = self.enumerator9.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running9 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running9 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running9 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter9 = self.enumerator9.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter9.SourceOnCompleted(Completed9Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed10(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running10 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter10.GetResult())
|
|
{
|
|
self.hasCurrent10 = true;
|
|
self.current10 = self.enumerator10.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running10 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running10 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running10 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter10 = self.enumerator10.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter10.SourceOnCompleted(Completed10Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed11(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running11 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter11.GetResult())
|
|
{
|
|
self.hasCurrent11 = true;
|
|
self.current11 = self.enumerator11.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running11 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running11 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running11 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter11 = self.enumerator11.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter11.SourceOnCompleted(Completed11Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
bool TrySetResult()
|
|
{
|
|
if (hasCurrent1 && hasCurrent2 && hasCurrent3 && hasCurrent4 && hasCurrent5 && hasCurrent6 && hasCurrent7 && hasCurrent8 && hasCurrent9 && hasCurrent10 && hasCurrent11)
|
|
{
|
|
result = resultSelector(current1, current2, current3, current4, current5, current6, current7, current8, current9, current10, current11);
|
|
completionSource.TrySetResult(true);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async UniTask DisposeAsync()
|
|
{
|
|
TaskTracker.RemoveTracking(this);
|
|
if (enumerator1 != null)
|
|
{
|
|
await enumerator1.DisposeAsync();
|
|
}
|
|
if (enumerator2 != null)
|
|
{
|
|
await enumerator2.DisposeAsync();
|
|
}
|
|
if (enumerator3 != null)
|
|
{
|
|
await enumerator3.DisposeAsync();
|
|
}
|
|
if (enumerator4 != null)
|
|
{
|
|
await enumerator4.DisposeAsync();
|
|
}
|
|
if (enumerator5 != null)
|
|
{
|
|
await enumerator5.DisposeAsync();
|
|
}
|
|
if (enumerator6 != null)
|
|
{
|
|
await enumerator6.DisposeAsync();
|
|
}
|
|
if (enumerator7 != null)
|
|
{
|
|
await enumerator7.DisposeAsync();
|
|
}
|
|
if (enumerator8 != null)
|
|
{
|
|
await enumerator8.DisposeAsync();
|
|
}
|
|
if (enumerator9 != null)
|
|
{
|
|
await enumerator9.DisposeAsync();
|
|
}
|
|
if (enumerator10 != null)
|
|
{
|
|
await enumerator10.DisposeAsync();
|
|
}
|
|
if (enumerator11 != null)
|
|
{
|
|
await enumerator11.DisposeAsync();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
internal class CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult> : IUniTaskAsyncEnumerable<TResult>
|
|
{
|
|
readonly IUniTaskAsyncEnumerable<T1> source1;
|
|
readonly IUniTaskAsyncEnumerable<T2> source2;
|
|
readonly IUniTaskAsyncEnumerable<T3> source3;
|
|
readonly IUniTaskAsyncEnumerable<T4> source4;
|
|
readonly IUniTaskAsyncEnumerable<T5> source5;
|
|
readonly IUniTaskAsyncEnumerable<T6> source6;
|
|
readonly IUniTaskAsyncEnumerable<T7> source7;
|
|
readonly IUniTaskAsyncEnumerable<T8> source8;
|
|
readonly IUniTaskAsyncEnumerable<T9> source9;
|
|
readonly IUniTaskAsyncEnumerable<T10> source10;
|
|
readonly IUniTaskAsyncEnumerable<T11> source11;
|
|
readonly IUniTaskAsyncEnumerable<T12> source12;
|
|
|
|
readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult> resultSelector;
|
|
|
|
public CombineLatest(IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, IUniTaskAsyncEnumerable<T7> source7, IUniTaskAsyncEnumerable<T8> source8, IUniTaskAsyncEnumerable<T9> source9, IUniTaskAsyncEnumerable<T10> source10, IUniTaskAsyncEnumerable<T11> source11, IUniTaskAsyncEnumerable<T12> source12, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult> resultSelector)
|
|
{
|
|
this.source1 = source1;
|
|
this.source2 = source2;
|
|
this.source3 = source3;
|
|
this.source4 = source4;
|
|
this.source5 = source5;
|
|
this.source6 = source6;
|
|
this.source7 = source7;
|
|
this.source8 = source8;
|
|
this.source9 = source9;
|
|
this.source10 = source10;
|
|
this.source11 = source11;
|
|
this.source12 = source12;
|
|
|
|
this.resultSelector = resultSelector;
|
|
}
|
|
|
|
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
|
{
|
|
return new _CombineLatest(source1, source2, source3, source4, source5, source6, source7, source8, source9, source10, source11, source12, resultSelector, cancellationToken);
|
|
}
|
|
|
|
class _CombineLatest : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
|
|
{
|
|
static readonly Action<object> Completed1Delegate = Completed1;
|
|
static readonly Action<object> Completed2Delegate = Completed2;
|
|
static readonly Action<object> Completed3Delegate = Completed3;
|
|
static readonly Action<object> Completed4Delegate = Completed4;
|
|
static readonly Action<object> Completed5Delegate = Completed5;
|
|
static readonly Action<object> Completed6Delegate = Completed6;
|
|
static readonly Action<object> Completed7Delegate = Completed7;
|
|
static readonly Action<object> Completed8Delegate = Completed8;
|
|
static readonly Action<object> Completed9Delegate = Completed9;
|
|
static readonly Action<object> Completed10Delegate = Completed10;
|
|
static readonly Action<object> Completed11Delegate = Completed11;
|
|
static readonly Action<object> Completed12Delegate = Completed12;
|
|
const int CompleteCount = 12;
|
|
|
|
readonly IUniTaskAsyncEnumerable<T1> source1;
|
|
readonly IUniTaskAsyncEnumerable<T2> source2;
|
|
readonly IUniTaskAsyncEnumerable<T3> source3;
|
|
readonly IUniTaskAsyncEnumerable<T4> source4;
|
|
readonly IUniTaskAsyncEnumerable<T5> source5;
|
|
readonly IUniTaskAsyncEnumerable<T6> source6;
|
|
readonly IUniTaskAsyncEnumerable<T7> source7;
|
|
readonly IUniTaskAsyncEnumerable<T8> source8;
|
|
readonly IUniTaskAsyncEnumerable<T9> source9;
|
|
readonly IUniTaskAsyncEnumerable<T10> source10;
|
|
readonly IUniTaskAsyncEnumerable<T11> source11;
|
|
readonly IUniTaskAsyncEnumerable<T12> source12;
|
|
|
|
readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult> resultSelector;
|
|
CancellationToken cancellationToken;
|
|
|
|
IUniTaskAsyncEnumerator<T1> enumerator1;
|
|
UniTask<bool>.Awaiter awaiter1;
|
|
bool hasCurrent1;
|
|
bool running1;
|
|
T1 current1;
|
|
|
|
IUniTaskAsyncEnumerator<T2> enumerator2;
|
|
UniTask<bool>.Awaiter awaiter2;
|
|
bool hasCurrent2;
|
|
bool running2;
|
|
T2 current2;
|
|
|
|
IUniTaskAsyncEnumerator<T3> enumerator3;
|
|
UniTask<bool>.Awaiter awaiter3;
|
|
bool hasCurrent3;
|
|
bool running3;
|
|
T3 current3;
|
|
|
|
IUniTaskAsyncEnumerator<T4> enumerator4;
|
|
UniTask<bool>.Awaiter awaiter4;
|
|
bool hasCurrent4;
|
|
bool running4;
|
|
T4 current4;
|
|
|
|
IUniTaskAsyncEnumerator<T5> enumerator5;
|
|
UniTask<bool>.Awaiter awaiter5;
|
|
bool hasCurrent5;
|
|
bool running5;
|
|
T5 current5;
|
|
|
|
IUniTaskAsyncEnumerator<T6> enumerator6;
|
|
UniTask<bool>.Awaiter awaiter6;
|
|
bool hasCurrent6;
|
|
bool running6;
|
|
T6 current6;
|
|
|
|
IUniTaskAsyncEnumerator<T7> enumerator7;
|
|
UniTask<bool>.Awaiter awaiter7;
|
|
bool hasCurrent7;
|
|
bool running7;
|
|
T7 current7;
|
|
|
|
IUniTaskAsyncEnumerator<T8> enumerator8;
|
|
UniTask<bool>.Awaiter awaiter8;
|
|
bool hasCurrent8;
|
|
bool running8;
|
|
T8 current8;
|
|
|
|
IUniTaskAsyncEnumerator<T9> enumerator9;
|
|
UniTask<bool>.Awaiter awaiter9;
|
|
bool hasCurrent9;
|
|
bool running9;
|
|
T9 current9;
|
|
|
|
IUniTaskAsyncEnumerator<T10> enumerator10;
|
|
UniTask<bool>.Awaiter awaiter10;
|
|
bool hasCurrent10;
|
|
bool running10;
|
|
T10 current10;
|
|
|
|
IUniTaskAsyncEnumerator<T11> enumerator11;
|
|
UniTask<bool>.Awaiter awaiter11;
|
|
bool hasCurrent11;
|
|
bool running11;
|
|
T11 current11;
|
|
|
|
IUniTaskAsyncEnumerator<T12> enumerator12;
|
|
UniTask<bool>.Awaiter awaiter12;
|
|
bool hasCurrent12;
|
|
bool running12;
|
|
T12 current12;
|
|
|
|
int completedCount;
|
|
bool syncRunning;
|
|
TResult result;
|
|
|
|
public _CombineLatest(IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, IUniTaskAsyncEnumerable<T7> source7, IUniTaskAsyncEnumerable<T8> source8, IUniTaskAsyncEnumerable<T9> source9, IUniTaskAsyncEnumerable<T10> source10, IUniTaskAsyncEnumerable<T11> source11, IUniTaskAsyncEnumerable<T12> source12, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TResult> resultSelector, CancellationToken cancellationToken)
|
|
{
|
|
this.source1 = source1;
|
|
this.source2 = source2;
|
|
this.source3 = source3;
|
|
this.source4 = source4;
|
|
this.source5 = source5;
|
|
this.source6 = source6;
|
|
this.source7 = source7;
|
|
this.source8 = source8;
|
|
this.source9 = source9;
|
|
this.source10 = source10;
|
|
this.source11 = source11;
|
|
this.source12 = source12;
|
|
|
|
this.resultSelector = resultSelector;
|
|
this.cancellationToken = cancellationToken;
|
|
TaskTracker.TrackActiveTask(this, 3);
|
|
}
|
|
|
|
public TResult Current => result;
|
|
|
|
public UniTask<bool> MoveNextAsync()
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
if (completedCount == CompleteCount) return CompletedTasks.False;
|
|
|
|
if (enumerator1 == null)
|
|
{
|
|
enumerator1 = source1.GetAsyncEnumerator(cancellationToken);
|
|
enumerator2 = source2.GetAsyncEnumerator(cancellationToken);
|
|
enumerator3 = source3.GetAsyncEnumerator(cancellationToken);
|
|
enumerator4 = source4.GetAsyncEnumerator(cancellationToken);
|
|
enumerator5 = source5.GetAsyncEnumerator(cancellationToken);
|
|
enumerator6 = source6.GetAsyncEnumerator(cancellationToken);
|
|
enumerator7 = source7.GetAsyncEnumerator(cancellationToken);
|
|
enumerator8 = source8.GetAsyncEnumerator(cancellationToken);
|
|
enumerator9 = source9.GetAsyncEnumerator(cancellationToken);
|
|
enumerator10 = source10.GetAsyncEnumerator(cancellationToken);
|
|
enumerator11 = source11.GetAsyncEnumerator(cancellationToken);
|
|
enumerator12 = source12.GetAsyncEnumerator(cancellationToken);
|
|
}
|
|
|
|
completionSource.Reset();
|
|
|
|
AGAIN:
|
|
syncRunning = true;
|
|
if (!running1)
|
|
{
|
|
running1 = true;
|
|
awaiter1 = enumerator1.MoveNextAsync().GetAwaiter();
|
|
if (awaiter1.IsCompleted)
|
|
{
|
|
Completed1(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter1.SourceOnCompleted(Completed1Delegate, this);
|
|
}
|
|
}
|
|
if (!running2)
|
|
{
|
|
running2 = true;
|
|
awaiter2 = enumerator2.MoveNextAsync().GetAwaiter();
|
|
if (awaiter2.IsCompleted)
|
|
{
|
|
Completed2(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter2.SourceOnCompleted(Completed2Delegate, this);
|
|
}
|
|
}
|
|
if (!running3)
|
|
{
|
|
running3 = true;
|
|
awaiter3 = enumerator3.MoveNextAsync().GetAwaiter();
|
|
if (awaiter3.IsCompleted)
|
|
{
|
|
Completed3(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter3.SourceOnCompleted(Completed3Delegate, this);
|
|
}
|
|
}
|
|
if (!running4)
|
|
{
|
|
running4 = true;
|
|
awaiter4 = enumerator4.MoveNextAsync().GetAwaiter();
|
|
if (awaiter4.IsCompleted)
|
|
{
|
|
Completed4(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter4.SourceOnCompleted(Completed4Delegate, this);
|
|
}
|
|
}
|
|
if (!running5)
|
|
{
|
|
running5 = true;
|
|
awaiter5 = enumerator5.MoveNextAsync().GetAwaiter();
|
|
if (awaiter5.IsCompleted)
|
|
{
|
|
Completed5(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter5.SourceOnCompleted(Completed5Delegate, this);
|
|
}
|
|
}
|
|
if (!running6)
|
|
{
|
|
running6 = true;
|
|
awaiter6 = enumerator6.MoveNextAsync().GetAwaiter();
|
|
if (awaiter6.IsCompleted)
|
|
{
|
|
Completed6(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter6.SourceOnCompleted(Completed6Delegate, this);
|
|
}
|
|
}
|
|
if (!running7)
|
|
{
|
|
running7 = true;
|
|
awaiter7 = enumerator7.MoveNextAsync().GetAwaiter();
|
|
if (awaiter7.IsCompleted)
|
|
{
|
|
Completed7(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter7.SourceOnCompleted(Completed7Delegate, this);
|
|
}
|
|
}
|
|
if (!running8)
|
|
{
|
|
running8 = true;
|
|
awaiter8 = enumerator8.MoveNextAsync().GetAwaiter();
|
|
if (awaiter8.IsCompleted)
|
|
{
|
|
Completed8(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter8.SourceOnCompleted(Completed8Delegate, this);
|
|
}
|
|
}
|
|
if (!running9)
|
|
{
|
|
running9 = true;
|
|
awaiter9 = enumerator9.MoveNextAsync().GetAwaiter();
|
|
if (awaiter9.IsCompleted)
|
|
{
|
|
Completed9(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter9.SourceOnCompleted(Completed9Delegate, this);
|
|
}
|
|
}
|
|
if (!running10)
|
|
{
|
|
running10 = true;
|
|
awaiter10 = enumerator10.MoveNextAsync().GetAwaiter();
|
|
if (awaiter10.IsCompleted)
|
|
{
|
|
Completed10(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter10.SourceOnCompleted(Completed10Delegate, this);
|
|
}
|
|
}
|
|
if (!running11)
|
|
{
|
|
running11 = true;
|
|
awaiter11 = enumerator11.MoveNextAsync().GetAwaiter();
|
|
if (awaiter11.IsCompleted)
|
|
{
|
|
Completed11(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter11.SourceOnCompleted(Completed11Delegate, this);
|
|
}
|
|
}
|
|
if (!running12)
|
|
{
|
|
running12 = true;
|
|
awaiter12 = enumerator12.MoveNextAsync().GetAwaiter();
|
|
if (awaiter12.IsCompleted)
|
|
{
|
|
Completed12(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter12.SourceOnCompleted(Completed12Delegate, this);
|
|
}
|
|
}
|
|
|
|
if (!running1 || !running2 || !running3 || !running4 || !running5 || !running6 || !running7 || !running8 || !running9 || !running10 || !running11 || !running12)
|
|
{
|
|
goto AGAIN;
|
|
}
|
|
syncRunning = false;
|
|
|
|
return new UniTask<bool>(this, completionSource.Version);
|
|
}
|
|
|
|
static void Completed1(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running1 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter1.GetResult())
|
|
{
|
|
self.hasCurrent1 = true;
|
|
self.current1 = self.enumerator1.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter1 = self.enumerator1.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter1.SourceOnCompleted(Completed1Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed2(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running2 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter2.GetResult())
|
|
{
|
|
self.hasCurrent2 = true;
|
|
self.current2 = self.enumerator2.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter2 = self.enumerator2.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter2.SourceOnCompleted(Completed2Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed3(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running3 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter3.GetResult())
|
|
{
|
|
self.hasCurrent3 = true;
|
|
self.current3 = self.enumerator3.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter3 = self.enumerator3.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter3.SourceOnCompleted(Completed3Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed4(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running4 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter4.GetResult())
|
|
{
|
|
self.hasCurrent4 = true;
|
|
self.current4 = self.enumerator4.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter4 = self.enumerator4.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter4.SourceOnCompleted(Completed4Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed5(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running5 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter5.GetResult())
|
|
{
|
|
self.hasCurrent5 = true;
|
|
self.current5 = self.enumerator5.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter5 = self.enumerator5.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter5.SourceOnCompleted(Completed5Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed6(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running6 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter6.GetResult())
|
|
{
|
|
self.hasCurrent6 = true;
|
|
self.current6 = self.enumerator6.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter6 = self.enumerator6.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter6.SourceOnCompleted(Completed6Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed7(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running7 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter7.GetResult())
|
|
{
|
|
self.hasCurrent7 = true;
|
|
self.current7 = self.enumerator7.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running7 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running7 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running7 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter7 = self.enumerator7.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter7.SourceOnCompleted(Completed7Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed8(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running8 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter8.GetResult())
|
|
{
|
|
self.hasCurrent8 = true;
|
|
self.current8 = self.enumerator8.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running8 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running8 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running8 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter8 = self.enumerator8.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter8.SourceOnCompleted(Completed8Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed9(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running9 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter9.GetResult())
|
|
{
|
|
self.hasCurrent9 = true;
|
|
self.current9 = self.enumerator9.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running9 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running9 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running9 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter9 = self.enumerator9.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter9.SourceOnCompleted(Completed9Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed10(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running10 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter10.GetResult())
|
|
{
|
|
self.hasCurrent10 = true;
|
|
self.current10 = self.enumerator10.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running10 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running10 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running10 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter10 = self.enumerator10.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter10.SourceOnCompleted(Completed10Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed11(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running11 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter11.GetResult())
|
|
{
|
|
self.hasCurrent11 = true;
|
|
self.current11 = self.enumerator11.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running11 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running11 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running11 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter11 = self.enumerator11.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter11.SourceOnCompleted(Completed11Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed12(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running12 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter12.GetResult())
|
|
{
|
|
self.hasCurrent12 = true;
|
|
self.current12 = self.enumerator12.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running12 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running12 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running12 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter12 = self.enumerator12.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter12.SourceOnCompleted(Completed12Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
bool TrySetResult()
|
|
{
|
|
if (hasCurrent1 && hasCurrent2 && hasCurrent3 && hasCurrent4 && hasCurrent5 && hasCurrent6 && hasCurrent7 && hasCurrent8 && hasCurrent9 && hasCurrent10 && hasCurrent11 && hasCurrent12)
|
|
{
|
|
result = resultSelector(current1, current2, current3, current4, current5, current6, current7, current8, current9, current10, current11, current12);
|
|
completionSource.TrySetResult(true);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async UniTask DisposeAsync()
|
|
{
|
|
TaskTracker.RemoveTracking(this);
|
|
if (enumerator1 != null)
|
|
{
|
|
await enumerator1.DisposeAsync();
|
|
}
|
|
if (enumerator2 != null)
|
|
{
|
|
await enumerator2.DisposeAsync();
|
|
}
|
|
if (enumerator3 != null)
|
|
{
|
|
await enumerator3.DisposeAsync();
|
|
}
|
|
if (enumerator4 != null)
|
|
{
|
|
await enumerator4.DisposeAsync();
|
|
}
|
|
if (enumerator5 != null)
|
|
{
|
|
await enumerator5.DisposeAsync();
|
|
}
|
|
if (enumerator6 != null)
|
|
{
|
|
await enumerator6.DisposeAsync();
|
|
}
|
|
if (enumerator7 != null)
|
|
{
|
|
await enumerator7.DisposeAsync();
|
|
}
|
|
if (enumerator8 != null)
|
|
{
|
|
await enumerator8.DisposeAsync();
|
|
}
|
|
if (enumerator9 != null)
|
|
{
|
|
await enumerator9.DisposeAsync();
|
|
}
|
|
if (enumerator10 != null)
|
|
{
|
|
await enumerator10.DisposeAsync();
|
|
}
|
|
if (enumerator11 != null)
|
|
{
|
|
await enumerator11.DisposeAsync();
|
|
}
|
|
if (enumerator12 != null)
|
|
{
|
|
await enumerator12.DisposeAsync();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
internal class CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult> : IUniTaskAsyncEnumerable<TResult>
|
|
{
|
|
readonly IUniTaskAsyncEnumerable<T1> source1;
|
|
readonly IUniTaskAsyncEnumerable<T2> source2;
|
|
readonly IUniTaskAsyncEnumerable<T3> source3;
|
|
readonly IUniTaskAsyncEnumerable<T4> source4;
|
|
readonly IUniTaskAsyncEnumerable<T5> source5;
|
|
readonly IUniTaskAsyncEnumerable<T6> source6;
|
|
readonly IUniTaskAsyncEnumerable<T7> source7;
|
|
readonly IUniTaskAsyncEnumerable<T8> source8;
|
|
readonly IUniTaskAsyncEnumerable<T9> source9;
|
|
readonly IUniTaskAsyncEnumerable<T10> source10;
|
|
readonly IUniTaskAsyncEnumerable<T11> source11;
|
|
readonly IUniTaskAsyncEnumerable<T12> source12;
|
|
readonly IUniTaskAsyncEnumerable<T13> source13;
|
|
|
|
readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult> resultSelector;
|
|
|
|
public CombineLatest(IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, IUniTaskAsyncEnumerable<T7> source7, IUniTaskAsyncEnumerable<T8> source8, IUniTaskAsyncEnumerable<T9> source9, IUniTaskAsyncEnumerable<T10> source10, IUniTaskAsyncEnumerable<T11> source11, IUniTaskAsyncEnumerable<T12> source12, IUniTaskAsyncEnumerable<T13> source13, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult> resultSelector)
|
|
{
|
|
this.source1 = source1;
|
|
this.source2 = source2;
|
|
this.source3 = source3;
|
|
this.source4 = source4;
|
|
this.source5 = source5;
|
|
this.source6 = source6;
|
|
this.source7 = source7;
|
|
this.source8 = source8;
|
|
this.source9 = source9;
|
|
this.source10 = source10;
|
|
this.source11 = source11;
|
|
this.source12 = source12;
|
|
this.source13 = source13;
|
|
|
|
this.resultSelector = resultSelector;
|
|
}
|
|
|
|
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
|
{
|
|
return new _CombineLatest(source1, source2, source3, source4, source5, source6, source7, source8, source9, source10, source11, source12, source13, resultSelector, cancellationToken);
|
|
}
|
|
|
|
class _CombineLatest : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
|
|
{
|
|
static readonly Action<object> Completed1Delegate = Completed1;
|
|
static readonly Action<object> Completed2Delegate = Completed2;
|
|
static readonly Action<object> Completed3Delegate = Completed3;
|
|
static readonly Action<object> Completed4Delegate = Completed4;
|
|
static readonly Action<object> Completed5Delegate = Completed5;
|
|
static readonly Action<object> Completed6Delegate = Completed6;
|
|
static readonly Action<object> Completed7Delegate = Completed7;
|
|
static readonly Action<object> Completed8Delegate = Completed8;
|
|
static readonly Action<object> Completed9Delegate = Completed9;
|
|
static readonly Action<object> Completed10Delegate = Completed10;
|
|
static readonly Action<object> Completed11Delegate = Completed11;
|
|
static readonly Action<object> Completed12Delegate = Completed12;
|
|
static readonly Action<object> Completed13Delegate = Completed13;
|
|
const int CompleteCount = 13;
|
|
|
|
readonly IUniTaskAsyncEnumerable<T1> source1;
|
|
readonly IUniTaskAsyncEnumerable<T2> source2;
|
|
readonly IUniTaskAsyncEnumerable<T3> source3;
|
|
readonly IUniTaskAsyncEnumerable<T4> source4;
|
|
readonly IUniTaskAsyncEnumerable<T5> source5;
|
|
readonly IUniTaskAsyncEnumerable<T6> source6;
|
|
readonly IUniTaskAsyncEnumerable<T7> source7;
|
|
readonly IUniTaskAsyncEnumerable<T8> source8;
|
|
readonly IUniTaskAsyncEnumerable<T9> source9;
|
|
readonly IUniTaskAsyncEnumerable<T10> source10;
|
|
readonly IUniTaskAsyncEnumerable<T11> source11;
|
|
readonly IUniTaskAsyncEnumerable<T12> source12;
|
|
readonly IUniTaskAsyncEnumerable<T13> source13;
|
|
|
|
readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult> resultSelector;
|
|
CancellationToken cancellationToken;
|
|
|
|
IUniTaskAsyncEnumerator<T1> enumerator1;
|
|
UniTask<bool>.Awaiter awaiter1;
|
|
bool hasCurrent1;
|
|
bool running1;
|
|
T1 current1;
|
|
|
|
IUniTaskAsyncEnumerator<T2> enumerator2;
|
|
UniTask<bool>.Awaiter awaiter2;
|
|
bool hasCurrent2;
|
|
bool running2;
|
|
T2 current2;
|
|
|
|
IUniTaskAsyncEnumerator<T3> enumerator3;
|
|
UniTask<bool>.Awaiter awaiter3;
|
|
bool hasCurrent3;
|
|
bool running3;
|
|
T3 current3;
|
|
|
|
IUniTaskAsyncEnumerator<T4> enumerator4;
|
|
UniTask<bool>.Awaiter awaiter4;
|
|
bool hasCurrent4;
|
|
bool running4;
|
|
T4 current4;
|
|
|
|
IUniTaskAsyncEnumerator<T5> enumerator5;
|
|
UniTask<bool>.Awaiter awaiter5;
|
|
bool hasCurrent5;
|
|
bool running5;
|
|
T5 current5;
|
|
|
|
IUniTaskAsyncEnumerator<T6> enumerator6;
|
|
UniTask<bool>.Awaiter awaiter6;
|
|
bool hasCurrent6;
|
|
bool running6;
|
|
T6 current6;
|
|
|
|
IUniTaskAsyncEnumerator<T7> enumerator7;
|
|
UniTask<bool>.Awaiter awaiter7;
|
|
bool hasCurrent7;
|
|
bool running7;
|
|
T7 current7;
|
|
|
|
IUniTaskAsyncEnumerator<T8> enumerator8;
|
|
UniTask<bool>.Awaiter awaiter8;
|
|
bool hasCurrent8;
|
|
bool running8;
|
|
T8 current8;
|
|
|
|
IUniTaskAsyncEnumerator<T9> enumerator9;
|
|
UniTask<bool>.Awaiter awaiter9;
|
|
bool hasCurrent9;
|
|
bool running9;
|
|
T9 current9;
|
|
|
|
IUniTaskAsyncEnumerator<T10> enumerator10;
|
|
UniTask<bool>.Awaiter awaiter10;
|
|
bool hasCurrent10;
|
|
bool running10;
|
|
T10 current10;
|
|
|
|
IUniTaskAsyncEnumerator<T11> enumerator11;
|
|
UniTask<bool>.Awaiter awaiter11;
|
|
bool hasCurrent11;
|
|
bool running11;
|
|
T11 current11;
|
|
|
|
IUniTaskAsyncEnumerator<T12> enumerator12;
|
|
UniTask<bool>.Awaiter awaiter12;
|
|
bool hasCurrent12;
|
|
bool running12;
|
|
T12 current12;
|
|
|
|
IUniTaskAsyncEnumerator<T13> enumerator13;
|
|
UniTask<bool>.Awaiter awaiter13;
|
|
bool hasCurrent13;
|
|
bool running13;
|
|
T13 current13;
|
|
|
|
int completedCount;
|
|
bool syncRunning;
|
|
TResult result;
|
|
|
|
public _CombineLatest(IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, IUniTaskAsyncEnumerable<T7> source7, IUniTaskAsyncEnumerable<T8> source8, IUniTaskAsyncEnumerable<T9> source9, IUniTaskAsyncEnumerable<T10> source10, IUniTaskAsyncEnumerable<T11> source11, IUniTaskAsyncEnumerable<T12> source12, IUniTaskAsyncEnumerable<T13> source13, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TResult> resultSelector, CancellationToken cancellationToken)
|
|
{
|
|
this.source1 = source1;
|
|
this.source2 = source2;
|
|
this.source3 = source3;
|
|
this.source4 = source4;
|
|
this.source5 = source5;
|
|
this.source6 = source6;
|
|
this.source7 = source7;
|
|
this.source8 = source8;
|
|
this.source9 = source9;
|
|
this.source10 = source10;
|
|
this.source11 = source11;
|
|
this.source12 = source12;
|
|
this.source13 = source13;
|
|
|
|
this.resultSelector = resultSelector;
|
|
this.cancellationToken = cancellationToken;
|
|
TaskTracker.TrackActiveTask(this, 3);
|
|
}
|
|
|
|
public TResult Current => result;
|
|
|
|
public UniTask<bool> MoveNextAsync()
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
if (completedCount == CompleteCount) return CompletedTasks.False;
|
|
|
|
if (enumerator1 == null)
|
|
{
|
|
enumerator1 = source1.GetAsyncEnumerator(cancellationToken);
|
|
enumerator2 = source2.GetAsyncEnumerator(cancellationToken);
|
|
enumerator3 = source3.GetAsyncEnumerator(cancellationToken);
|
|
enumerator4 = source4.GetAsyncEnumerator(cancellationToken);
|
|
enumerator5 = source5.GetAsyncEnumerator(cancellationToken);
|
|
enumerator6 = source6.GetAsyncEnumerator(cancellationToken);
|
|
enumerator7 = source7.GetAsyncEnumerator(cancellationToken);
|
|
enumerator8 = source8.GetAsyncEnumerator(cancellationToken);
|
|
enumerator9 = source9.GetAsyncEnumerator(cancellationToken);
|
|
enumerator10 = source10.GetAsyncEnumerator(cancellationToken);
|
|
enumerator11 = source11.GetAsyncEnumerator(cancellationToken);
|
|
enumerator12 = source12.GetAsyncEnumerator(cancellationToken);
|
|
enumerator13 = source13.GetAsyncEnumerator(cancellationToken);
|
|
}
|
|
|
|
completionSource.Reset();
|
|
|
|
AGAIN:
|
|
syncRunning = true;
|
|
if (!running1)
|
|
{
|
|
running1 = true;
|
|
awaiter1 = enumerator1.MoveNextAsync().GetAwaiter();
|
|
if (awaiter1.IsCompleted)
|
|
{
|
|
Completed1(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter1.SourceOnCompleted(Completed1Delegate, this);
|
|
}
|
|
}
|
|
if (!running2)
|
|
{
|
|
running2 = true;
|
|
awaiter2 = enumerator2.MoveNextAsync().GetAwaiter();
|
|
if (awaiter2.IsCompleted)
|
|
{
|
|
Completed2(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter2.SourceOnCompleted(Completed2Delegate, this);
|
|
}
|
|
}
|
|
if (!running3)
|
|
{
|
|
running3 = true;
|
|
awaiter3 = enumerator3.MoveNextAsync().GetAwaiter();
|
|
if (awaiter3.IsCompleted)
|
|
{
|
|
Completed3(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter3.SourceOnCompleted(Completed3Delegate, this);
|
|
}
|
|
}
|
|
if (!running4)
|
|
{
|
|
running4 = true;
|
|
awaiter4 = enumerator4.MoveNextAsync().GetAwaiter();
|
|
if (awaiter4.IsCompleted)
|
|
{
|
|
Completed4(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter4.SourceOnCompleted(Completed4Delegate, this);
|
|
}
|
|
}
|
|
if (!running5)
|
|
{
|
|
running5 = true;
|
|
awaiter5 = enumerator5.MoveNextAsync().GetAwaiter();
|
|
if (awaiter5.IsCompleted)
|
|
{
|
|
Completed5(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter5.SourceOnCompleted(Completed5Delegate, this);
|
|
}
|
|
}
|
|
if (!running6)
|
|
{
|
|
running6 = true;
|
|
awaiter6 = enumerator6.MoveNextAsync().GetAwaiter();
|
|
if (awaiter6.IsCompleted)
|
|
{
|
|
Completed6(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter6.SourceOnCompleted(Completed6Delegate, this);
|
|
}
|
|
}
|
|
if (!running7)
|
|
{
|
|
running7 = true;
|
|
awaiter7 = enumerator7.MoveNextAsync().GetAwaiter();
|
|
if (awaiter7.IsCompleted)
|
|
{
|
|
Completed7(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter7.SourceOnCompleted(Completed7Delegate, this);
|
|
}
|
|
}
|
|
if (!running8)
|
|
{
|
|
running8 = true;
|
|
awaiter8 = enumerator8.MoveNextAsync().GetAwaiter();
|
|
if (awaiter8.IsCompleted)
|
|
{
|
|
Completed8(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter8.SourceOnCompleted(Completed8Delegate, this);
|
|
}
|
|
}
|
|
if (!running9)
|
|
{
|
|
running9 = true;
|
|
awaiter9 = enumerator9.MoveNextAsync().GetAwaiter();
|
|
if (awaiter9.IsCompleted)
|
|
{
|
|
Completed9(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter9.SourceOnCompleted(Completed9Delegate, this);
|
|
}
|
|
}
|
|
if (!running10)
|
|
{
|
|
running10 = true;
|
|
awaiter10 = enumerator10.MoveNextAsync().GetAwaiter();
|
|
if (awaiter10.IsCompleted)
|
|
{
|
|
Completed10(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter10.SourceOnCompleted(Completed10Delegate, this);
|
|
}
|
|
}
|
|
if (!running11)
|
|
{
|
|
running11 = true;
|
|
awaiter11 = enumerator11.MoveNextAsync().GetAwaiter();
|
|
if (awaiter11.IsCompleted)
|
|
{
|
|
Completed11(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter11.SourceOnCompleted(Completed11Delegate, this);
|
|
}
|
|
}
|
|
if (!running12)
|
|
{
|
|
running12 = true;
|
|
awaiter12 = enumerator12.MoveNextAsync().GetAwaiter();
|
|
if (awaiter12.IsCompleted)
|
|
{
|
|
Completed12(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter12.SourceOnCompleted(Completed12Delegate, this);
|
|
}
|
|
}
|
|
if (!running13)
|
|
{
|
|
running13 = true;
|
|
awaiter13 = enumerator13.MoveNextAsync().GetAwaiter();
|
|
if (awaiter13.IsCompleted)
|
|
{
|
|
Completed13(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter13.SourceOnCompleted(Completed13Delegate, this);
|
|
}
|
|
}
|
|
|
|
if (!running1 || !running2 || !running3 || !running4 || !running5 || !running6 || !running7 || !running8 || !running9 || !running10 || !running11 || !running12 || !running13)
|
|
{
|
|
goto AGAIN;
|
|
}
|
|
syncRunning = false;
|
|
|
|
return new UniTask<bool>(this, completionSource.Version);
|
|
}
|
|
|
|
static void Completed1(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running1 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter1.GetResult())
|
|
{
|
|
self.hasCurrent1 = true;
|
|
self.current1 = self.enumerator1.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter1 = self.enumerator1.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter1.SourceOnCompleted(Completed1Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed2(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running2 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter2.GetResult())
|
|
{
|
|
self.hasCurrent2 = true;
|
|
self.current2 = self.enumerator2.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter2 = self.enumerator2.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter2.SourceOnCompleted(Completed2Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed3(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running3 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter3.GetResult())
|
|
{
|
|
self.hasCurrent3 = true;
|
|
self.current3 = self.enumerator3.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter3 = self.enumerator3.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter3.SourceOnCompleted(Completed3Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed4(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running4 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter4.GetResult())
|
|
{
|
|
self.hasCurrent4 = true;
|
|
self.current4 = self.enumerator4.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter4 = self.enumerator4.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter4.SourceOnCompleted(Completed4Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed5(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running5 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter5.GetResult())
|
|
{
|
|
self.hasCurrent5 = true;
|
|
self.current5 = self.enumerator5.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter5 = self.enumerator5.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter5.SourceOnCompleted(Completed5Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed6(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running6 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter6.GetResult())
|
|
{
|
|
self.hasCurrent6 = true;
|
|
self.current6 = self.enumerator6.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter6 = self.enumerator6.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter6.SourceOnCompleted(Completed6Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed7(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running7 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter7.GetResult())
|
|
{
|
|
self.hasCurrent7 = true;
|
|
self.current7 = self.enumerator7.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running7 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running7 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running7 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter7 = self.enumerator7.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter7.SourceOnCompleted(Completed7Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed8(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running8 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter8.GetResult())
|
|
{
|
|
self.hasCurrent8 = true;
|
|
self.current8 = self.enumerator8.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running8 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running8 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running8 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter8 = self.enumerator8.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter8.SourceOnCompleted(Completed8Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed9(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running9 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter9.GetResult())
|
|
{
|
|
self.hasCurrent9 = true;
|
|
self.current9 = self.enumerator9.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running9 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running9 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running9 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter9 = self.enumerator9.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter9.SourceOnCompleted(Completed9Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed10(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running10 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter10.GetResult())
|
|
{
|
|
self.hasCurrent10 = true;
|
|
self.current10 = self.enumerator10.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running10 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running10 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running10 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter10 = self.enumerator10.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter10.SourceOnCompleted(Completed10Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed11(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running11 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter11.GetResult())
|
|
{
|
|
self.hasCurrent11 = true;
|
|
self.current11 = self.enumerator11.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running11 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running11 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running11 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter11 = self.enumerator11.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter11.SourceOnCompleted(Completed11Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed12(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running12 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter12.GetResult())
|
|
{
|
|
self.hasCurrent12 = true;
|
|
self.current12 = self.enumerator12.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running12 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running12 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running12 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter12 = self.enumerator12.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter12.SourceOnCompleted(Completed12Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed13(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running13 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter13.GetResult())
|
|
{
|
|
self.hasCurrent13 = true;
|
|
self.current13 = self.enumerator13.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running13 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running13 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running13 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter13 = self.enumerator13.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter13.SourceOnCompleted(Completed13Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
bool TrySetResult()
|
|
{
|
|
if (hasCurrent1 && hasCurrent2 && hasCurrent3 && hasCurrent4 && hasCurrent5 && hasCurrent6 && hasCurrent7 && hasCurrent8 && hasCurrent9 && hasCurrent10 && hasCurrent11 && hasCurrent12 && hasCurrent13)
|
|
{
|
|
result = resultSelector(current1, current2, current3, current4, current5, current6, current7, current8, current9, current10, current11, current12, current13);
|
|
completionSource.TrySetResult(true);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async UniTask DisposeAsync()
|
|
{
|
|
TaskTracker.RemoveTracking(this);
|
|
if (enumerator1 != null)
|
|
{
|
|
await enumerator1.DisposeAsync();
|
|
}
|
|
if (enumerator2 != null)
|
|
{
|
|
await enumerator2.DisposeAsync();
|
|
}
|
|
if (enumerator3 != null)
|
|
{
|
|
await enumerator3.DisposeAsync();
|
|
}
|
|
if (enumerator4 != null)
|
|
{
|
|
await enumerator4.DisposeAsync();
|
|
}
|
|
if (enumerator5 != null)
|
|
{
|
|
await enumerator5.DisposeAsync();
|
|
}
|
|
if (enumerator6 != null)
|
|
{
|
|
await enumerator6.DisposeAsync();
|
|
}
|
|
if (enumerator7 != null)
|
|
{
|
|
await enumerator7.DisposeAsync();
|
|
}
|
|
if (enumerator8 != null)
|
|
{
|
|
await enumerator8.DisposeAsync();
|
|
}
|
|
if (enumerator9 != null)
|
|
{
|
|
await enumerator9.DisposeAsync();
|
|
}
|
|
if (enumerator10 != null)
|
|
{
|
|
await enumerator10.DisposeAsync();
|
|
}
|
|
if (enumerator11 != null)
|
|
{
|
|
await enumerator11.DisposeAsync();
|
|
}
|
|
if (enumerator12 != null)
|
|
{
|
|
await enumerator12.DisposeAsync();
|
|
}
|
|
if (enumerator13 != null)
|
|
{
|
|
await enumerator13.DisposeAsync();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
internal class CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult> : IUniTaskAsyncEnumerable<TResult>
|
|
{
|
|
readonly IUniTaskAsyncEnumerable<T1> source1;
|
|
readonly IUniTaskAsyncEnumerable<T2> source2;
|
|
readonly IUniTaskAsyncEnumerable<T3> source3;
|
|
readonly IUniTaskAsyncEnumerable<T4> source4;
|
|
readonly IUniTaskAsyncEnumerable<T5> source5;
|
|
readonly IUniTaskAsyncEnumerable<T6> source6;
|
|
readonly IUniTaskAsyncEnumerable<T7> source7;
|
|
readonly IUniTaskAsyncEnumerable<T8> source8;
|
|
readonly IUniTaskAsyncEnumerable<T9> source9;
|
|
readonly IUniTaskAsyncEnumerable<T10> source10;
|
|
readonly IUniTaskAsyncEnumerable<T11> source11;
|
|
readonly IUniTaskAsyncEnumerable<T12> source12;
|
|
readonly IUniTaskAsyncEnumerable<T13> source13;
|
|
readonly IUniTaskAsyncEnumerable<T14> source14;
|
|
|
|
readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult> resultSelector;
|
|
|
|
public CombineLatest(IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, IUniTaskAsyncEnumerable<T7> source7, IUniTaskAsyncEnumerable<T8> source8, IUniTaskAsyncEnumerable<T9> source9, IUniTaskAsyncEnumerable<T10> source10, IUniTaskAsyncEnumerable<T11> source11, IUniTaskAsyncEnumerable<T12> source12, IUniTaskAsyncEnumerable<T13> source13, IUniTaskAsyncEnumerable<T14> source14, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult> resultSelector)
|
|
{
|
|
this.source1 = source1;
|
|
this.source2 = source2;
|
|
this.source3 = source3;
|
|
this.source4 = source4;
|
|
this.source5 = source5;
|
|
this.source6 = source6;
|
|
this.source7 = source7;
|
|
this.source8 = source8;
|
|
this.source9 = source9;
|
|
this.source10 = source10;
|
|
this.source11 = source11;
|
|
this.source12 = source12;
|
|
this.source13 = source13;
|
|
this.source14 = source14;
|
|
|
|
this.resultSelector = resultSelector;
|
|
}
|
|
|
|
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
|
{
|
|
return new _CombineLatest(source1, source2, source3, source4, source5, source6, source7, source8, source9, source10, source11, source12, source13, source14, resultSelector, cancellationToken);
|
|
}
|
|
|
|
class _CombineLatest : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
|
|
{
|
|
static readonly Action<object> Completed1Delegate = Completed1;
|
|
static readonly Action<object> Completed2Delegate = Completed2;
|
|
static readonly Action<object> Completed3Delegate = Completed3;
|
|
static readonly Action<object> Completed4Delegate = Completed4;
|
|
static readonly Action<object> Completed5Delegate = Completed5;
|
|
static readonly Action<object> Completed6Delegate = Completed6;
|
|
static readonly Action<object> Completed7Delegate = Completed7;
|
|
static readonly Action<object> Completed8Delegate = Completed8;
|
|
static readonly Action<object> Completed9Delegate = Completed9;
|
|
static readonly Action<object> Completed10Delegate = Completed10;
|
|
static readonly Action<object> Completed11Delegate = Completed11;
|
|
static readonly Action<object> Completed12Delegate = Completed12;
|
|
static readonly Action<object> Completed13Delegate = Completed13;
|
|
static readonly Action<object> Completed14Delegate = Completed14;
|
|
const int CompleteCount = 14;
|
|
|
|
readonly IUniTaskAsyncEnumerable<T1> source1;
|
|
readonly IUniTaskAsyncEnumerable<T2> source2;
|
|
readonly IUniTaskAsyncEnumerable<T3> source3;
|
|
readonly IUniTaskAsyncEnumerable<T4> source4;
|
|
readonly IUniTaskAsyncEnumerable<T5> source5;
|
|
readonly IUniTaskAsyncEnumerable<T6> source6;
|
|
readonly IUniTaskAsyncEnumerable<T7> source7;
|
|
readonly IUniTaskAsyncEnumerable<T8> source8;
|
|
readonly IUniTaskAsyncEnumerable<T9> source9;
|
|
readonly IUniTaskAsyncEnumerable<T10> source10;
|
|
readonly IUniTaskAsyncEnumerable<T11> source11;
|
|
readonly IUniTaskAsyncEnumerable<T12> source12;
|
|
readonly IUniTaskAsyncEnumerable<T13> source13;
|
|
readonly IUniTaskAsyncEnumerable<T14> source14;
|
|
|
|
readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult> resultSelector;
|
|
CancellationToken cancellationToken;
|
|
|
|
IUniTaskAsyncEnumerator<T1> enumerator1;
|
|
UniTask<bool>.Awaiter awaiter1;
|
|
bool hasCurrent1;
|
|
bool running1;
|
|
T1 current1;
|
|
|
|
IUniTaskAsyncEnumerator<T2> enumerator2;
|
|
UniTask<bool>.Awaiter awaiter2;
|
|
bool hasCurrent2;
|
|
bool running2;
|
|
T2 current2;
|
|
|
|
IUniTaskAsyncEnumerator<T3> enumerator3;
|
|
UniTask<bool>.Awaiter awaiter3;
|
|
bool hasCurrent3;
|
|
bool running3;
|
|
T3 current3;
|
|
|
|
IUniTaskAsyncEnumerator<T4> enumerator4;
|
|
UniTask<bool>.Awaiter awaiter4;
|
|
bool hasCurrent4;
|
|
bool running4;
|
|
T4 current4;
|
|
|
|
IUniTaskAsyncEnumerator<T5> enumerator5;
|
|
UniTask<bool>.Awaiter awaiter5;
|
|
bool hasCurrent5;
|
|
bool running5;
|
|
T5 current5;
|
|
|
|
IUniTaskAsyncEnumerator<T6> enumerator6;
|
|
UniTask<bool>.Awaiter awaiter6;
|
|
bool hasCurrent6;
|
|
bool running6;
|
|
T6 current6;
|
|
|
|
IUniTaskAsyncEnumerator<T7> enumerator7;
|
|
UniTask<bool>.Awaiter awaiter7;
|
|
bool hasCurrent7;
|
|
bool running7;
|
|
T7 current7;
|
|
|
|
IUniTaskAsyncEnumerator<T8> enumerator8;
|
|
UniTask<bool>.Awaiter awaiter8;
|
|
bool hasCurrent8;
|
|
bool running8;
|
|
T8 current8;
|
|
|
|
IUniTaskAsyncEnumerator<T9> enumerator9;
|
|
UniTask<bool>.Awaiter awaiter9;
|
|
bool hasCurrent9;
|
|
bool running9;
|
|
T9 current9;
|
|
|
|
IUniTaskAsyncEnumerator<T10> enumerator10;
|
|
UniTask<bool>.Awaiter awaiter10;
|
|
bool hasCurrent10;
|
|
bool running10;
|
|
T10 current10;
|
|
|
|
IUniTaskAsyncEnumerator<T11> enumerator11;
|
|
UniTask<bool>.Awaiter awaiter11;
|
|
bool hasCurrent11;
|
|
bool running11;
|
|
T11 current11;
|
|
|
|
IUniTaskAsyncEnumerator<T12> enumerator12;
|
|
UniTask<bool>.Awaiter awaiter12;
|
|
bool hasCurrent12;
|
|
bool running12;
|
|
T12 current12;
|
|
|
|
IUniTaskAsyncEnumerator<T13> enumerator13;
|
|
UniTask<bool>.Awaiter awaiter13;
|
|
bool hasCurrent13;
|
|
bool running13;
|
|
T13 current13;
|
|
|
|
IUniTaskAsyncEnumerator<T14> enumerator14;
|
|
UniTask<bool>.Awaiter awaiter14;
|
|
bool hasCurrent14;
|
|
bool running14;
|
|
T14 current14;
|
|
|
|
int completedCount;
|
|
bool syncRunning;
|
|
TResult result;
|
|
|
|
public _CombineLatest(IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, IUniTaskAsyncEnumerable<T7> source7, IUniTaskAsyncEnumerable<T8> source8, IUniTaskAsyncEnumerable<T9> source9, IUniTaskAsyncEnumerable<T10> source10, IUniTaskAsyncEnumerable<T11> source11, IUniTaskAsyncEnumerable<T12> source12, IUniTaskAsyncEnumerable<T13> source13, IUniTaskAsyncEnumerable<T14> source14, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TResult> resultSelector, CancellationToken cancellationToken)
|
|
{
|
|
this.source1 = source1;
|
|
this.source2 = source2;
|
|
this.source3 = source3;
|
|
this.source4 = source4;
|
|
this.source5 = source5;
|
|
this.source6 = source6;
|
|
this.source7 = source7;
|
|
this.source8 = source8;
|
|
this.source9 = source9;
|
|
this.source10 = source10;
|
|
this.source11 = source11;
|
|
this.source12 = source12;
|
|
this.source13 = source13;
|
|
this.source14 = source14;
|
|
|
|
this.resultSelector = resultSelector;
|
|
this.cancellationToken = cancellationToken;
|
|
TaskTracker.TrackActiveTask(this, 3);
|
|
}
|
|
|
|
public TResult Current => result;
|
|
|
|
public UniTask<bool> MoveNextAsync()
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
if (completedCount == CompleteCount) return CompletedTasks.False;
|
|
|
|
if (enumerator1 == null)
|
|
{
|
|
enumerator1 = source1.GetAsyncEnumerator(cancellationToken);
|
|
enumerator2 = source2.GetAsyncEnumerator(cancellationToken);
|
|
enumerator3 = source3.GetAsyncEnumerator(cancellationToken);
|
|
enumerator4 = source4.GetAsyncEnumerator(cancellationToken);
|
|
enumerator5 = source5.GetAsyncEnumerator(cancellationToken);
|
|
enumerator6 = source6.GetAsyncEnumerator(cancellationToken);
|
|
enumerator7 = source7.GetAsyncEnumerator(cancellationToken);
|
|
enumerator8 = source8.GetAsyncEnumerator(cancellationToken);
|
|
enumerator9 = source9.GetAsyncEnumerator(cancellationToken);
|
|
enumerator10 = source10.GetAsyncEnumerator(cancellationToken);
|
|
enumerator11 = source11.GetAsyncEnumerator(cancellationToken);
|
|
enumerator12 = source12.GetAsyncEnumerator(cancellationToken);
|
|
enumerator13 = source13.GetAsyncEnumerator(cancellationToken);
|
|
enumerator14 = source14.GetAsyncEnumerator(cancellationToken);
|
|
}
|
|
|
|
completionSource.Reset();
|
|
|
|
AGAIN:
|
|
syncRunning = true;
|
|
if (!running1)
|
|
{
|
|
running1 = true;
|
|
awaiter1 = enumerator1.MoveNextAsync().GetAwaiter();
|
|
if (awaiter1.IsCompleted)
|
|
{
|
|
Completed1(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter1.SourceOnCompleted(Completed1Delegate, this);
|
|
}
|
|
}
|
|
if (!running2)
|
|
{
|
|
running2 = true;
|
|
awaiter2 = enumerator2.MoveNextAsync().GetAwaiter();
|
|
if (awaiter2.IsCompleted)
|
|
{
|
|
Completed2(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter2.SourceOnCompleted(Completed2Delegate, this);
|
|
}
|
|
}
|
|
if (!running3)
|
|
{
|
|
running3 = true;
|
|
awaiter3 = enumerator3.MoveNextAsync().GetAwaiter();
|
|
if (awaiter3.IsCompleted)
|
|
{
|
|
Completed3(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter3.SourceOnCompleted(Completed3Delegate, this);
|
|
}
|
|
}
|
|
if (!running4)
|
|
{
|
|
running4 = true;
|
|
awaiter4 = enumerator4.MoveNextAsync().GetAwaiter();
|
|
if (awaiter4.IsCompleted)
|
|
{
|
|
Completed4(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter4.SourceOnCompleted(Completed4Delegate, this);
|
|
}
|
|
}
|
|
if (!running5)
|
|
{
|
|
running5 = true;
|
|
awaiter5 = enumerator5.MoveNextAsync().GetAwaiter();
|
|
if (awaiter5.IsCompleted)
|
|
{
|
|
Completed5(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter5.SourceOnCompleted(Completed5Delegate, this);
|
|
}
|
|
}
|
|
if (!running6)
|
|
{
|
|
running6 = true;
|
|
awaiter6 = enumerator6.MoveNextAsync().GetAwaiter();
|
|
if (awaiter6.IsCompleted)
|
|
{
|
|
Completed6(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter6.SourceOnCompleted(Completed6Delegate, this);
|
|
}
|
|
}
|
|
if (!running7)
|
|
{
|
|
running7 = true;
|
|
awaiter7 = enumerator7.MoveNextAsync().GetAwaiter();
|
|
if (awaiter7.IsCompleted)
|
|
{
|
|
Completed7(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter7.SourceOnCompleted(Completed7Delegate, this);
|
|
}
|
|
}
|
|
if (!running8)
|
|
{
|
|
running8 = true;
|
|
awaiter8 = enumerator8.MoveNextAsync().GetAwaiter();
|
|
if (awaiter8.IsCompleted)
|
|
{
|
|
Completed8(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter8.SourceOnCompleted(Completed8Delegate, this);
|
|
}
|
|
}
|
|
if (!running9)
|
|
{
|
|
running9 = true;
|
|
awaiter9 = enumerator9.MoveNextAsync().GetAwaiter();
|
|
if (awaiter9.IsCompleted)
|
|
{
|
|
Completed9(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter9.SourceOnCompleted(Completed9Delegate, this);
|
|
}
|
|
}
|
|
if (!running10)
|
|
{
|
|
running10 = true;
|
|
awaiter10 = enumerator10.MoveNextAsync().GetAwaiter();
|
|
if (awaiter10.IsCompleted)
|
|
{
|
|
Completed10(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter10.SourceOnCompleted(Completed10Delegate, this);
|
|
}
|
|
}
|
|
if (!running11)
|
|
{
|
|
running11 = true;
|
|
awaiter11 = enumerator11.MoveNextAsync().GetAwaiter();
|
|
if (awaiter11.IsCompleted)
|
|
{
|
|
Completed11(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter11.SourceOnCompleted(Completed11Delegate, this);
|
|
}
|
|
}
|
|
if (!running12)
|
|
{
|
|
running12 = true;
|
|
awaiter12 = enumerator12.MoveNextAsync().GetAwaiter();
|
|
if (awaiter12.IsCompleted)
|
|
{
|
|
Completed12(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter12.SourceOnCompleted(Completed12Delegate, this);
|
|
}
|
|
}
|
|
if (!running13)
|
|
{
|
|
running13 = true;
|
|
awaiter13 = enumerator13.MoveNextAsync().GetAwaiter();
|
|
if (awaiter13.IsCompleted)
|
|
{
|
|
Completed13(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter13.SourceOnCompleted(Completed13Delegate, this);
|
|
}
|
|
}
|
|
if (!running14)
|
|
{
|
|
running14 = true;
|
|
awaiter14 = enumerator14.MoveNextAsync().GetAwaiter();
|
|
if (awaiter14.IsCompleted)
|
|
{
|
|
Completed14(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter14.SourceOnCompleted(Completed14Delegate, this);
|
|
}
|
|
}
|
|
|
|
if (!running1 || !running2 || !running3 || !running4 || !running5 || !running6 || !running7 || !running8 || !running9 || !running10 || !running11 || !running12 || !running13 || !running14)
|
|
{
|
|
goto AGAIN;
|
|
}
|
|
syncRunning = false;
|
|
|
|
return new UniTask<bool>(this, completionSource.Version);
|
|
}
|
|
|
|
static void Completed1(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running1 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter1.GetResult())
|
|
{
|
|
self.hasCurrent1 = true;
|
|
self.current1 = self.enumerator1.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter1 = self.enumerator1.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter1.SourceOnCompleted(Completed1Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed2(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running2 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter2.GetResult())
|
|
{
|
|
self.hasCurrent2 = true;
|
|
self.current2 = self.enumerator2.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter2 = self.enumerator2.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter2.SourceOnCompleted(Completed2Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed3(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running3 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter3.GetResult())
|
|
{
|
|
self.hasCurrent3 = true;
|
|
self.current3 = self.enumerator3.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter3 = self.enumerator3.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter3.SourceOnCompleted(Completed3Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed4(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running4 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter4.GetResult())
|
|
{
|
|
self.hasCurrent4 = true;
|
|
self.current4 = self.enumerator4.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter4 = self.enumerator4.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter4.SourceOnCompleted(Completed4Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed5(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running5 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter5.GetResult())
|
|
{
|
|
self.hasCurrent5 = true;
|
|
self.current5 = self.enumerator5.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter5 = self.enumerator5.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter5.SourceOnCompleted(Completed5Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed6(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running6 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter6.GetResult())
|
|
{
|
|
self.hasCurrent6 = true;
|
|
self.current6 = self.enumerator6.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter6 = self.enumerator6.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter6.SourceOnCompleted(Completed6Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed7(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running7 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter7.GetResult())
|
|
{
|
|
self.hasCurrent7 = true;
|
|
self.current7 = self.enumerator7.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running7 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running7 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running7 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter7 = self.enumerator7.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter7.SourceOnCompleted(Completed7Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed8(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running8 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter8.GetResult())
|
|
{
|
|
self.hasCurrent8 = true;
|
|
self.current8 = self.enumerator8.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running8 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running8 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running8 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter8 = self.enumerator8.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter8.SourceOnCompleted(Completed8Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed9(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running9 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter9.GetResult())
|
|
{
|
|
self.hasCurrent9 = true;
|
|
self.current9 = self.enumerator9.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running9 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running9 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running9 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter9 = self.enumerator9.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter9.SourceOnCompleted(Completed9Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed10(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running10 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter10.GetResult())
|
|
{
|
|
self.hasCurrent10 = true;
|
|
self.current10 = self.enumerator10.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running10 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running10 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running10 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter10 = self.enumerator10.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter10.SourceOnCompleted(Completed10Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed11(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running11 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter11.GetResult())
|
|
{
|
|
self.hasCurrent11 = true;
|
|
self.current11 = self.enumerator11.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running11 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running11 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running11 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter11 = self.enumerator11.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter11.SourceOnCompleted(Completed11Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed12(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running12 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter12.GetResult())
|
|
{
|
|
self.hasCurrent12 = true;
|
|
self.current12 = self.enumerator12.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running12 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running12 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running12 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter12 = self.enumerator12.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter12.SourceOnCompleted(Completed12Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed13(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running13 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter13.GetResult())
|
|
{
|
|
self.hasCurrent13 = true;
|
|
self.current13 = self.enumerator13.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running13 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running13 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running13 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter13 = self.enumerator13.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter13.SourceOnCompleted(Completed13Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed14(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running14 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter14.GetResult())
|
|
{
|
|
self.hasCurrent14 = true;
|
|
self.current14 = self.enumerator14.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running14 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running14 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running14 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter14 = self.enumerator14.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter14.SourceOnCompleted(Completed14Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
bool TrySetResult()
|
|
{
|
|
if (hasCurrent1 && hasCurrent2 && hasCurrent3 && hasCurrent4 && hasCurrent5 && hasCurrent6 && hasCurrent7 && hasCurrent8 && hasCurrent9 && hasCurrent10 && hasCurrent11 && hasCurrent12 && hasCurrent13 && hasCurrent14)
|
|
{
|
|
result = resultSelector(current1, current2, current3, current4, current5, current6, current7, current8, current9, current10, current11, current12, current13, current14);
|
|
completionSource.TrySetResult(true);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async UniTask DisposeAsync()
|
|
{
|
|
TaskTracker.RemoveTracking(this);
|
|
if (enumerator1 != null)
|
|
{
|
|
await enumerator1.DisposeAsync();
|
|
}
|
|
if (enumerator2 != null)
|
|
{
|
|
await enumerator2.DisposeAsync();
|
|
}
|
|
if (enumerator3 != null)
|
|
{
|
|
await enumerator3.DisposeAsync();
|
|
}
|
|
if (enumerator4 != null)
|
|
{
|
|
await enumerator4.DisposeAsync();
|
|
}
|
|
if (enumerator5 != null)
|
|
{
|
|
await enumerator5.DisposeAsync();
|
|
}
|
|
if (enumerator6 != null)
|
|
{
|
|
await enumerator6.DisposeAsync();
|
|
}
|
|
if (enumerator7 != null)
|
|
{
|
|
await enumerator7.DisposeAsync();
|
|
}
|
|
if (enumerator8 != null)
|
|
{
|
|
await enumerator8.DisposeAsync();
|
|
}
|
|
if (enumerator9 != null)
|
|
{
|
|
await enumerator9.DisposeAsync();
|
|
}
|
|
if (enumerator10 != null)
|
|
{
|
|
await enumerator10.DisposeAsync();
|
|
}
|
|
if (enumerator11 != null)
|
|
{
|
|
await enumerator11.DisposeAsync();
|
|
}
|
|
if (enumerator12 != null)
|
|
{
|
|
await enumerator12.DisposeAsync();
|
|
}
|
|
if (enumerator13 != null)
|
|
{
|
|
await enumerator13.DisposeAsync();
|
|
}
|
|
if (enumerator14 != null)
|
|
{
|
|
await enumerator14.DisposeAsync();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
internal class CombineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult> : IUniTaskAsyncEnumerable<TResult>
|
|
{
|
|
readonly IUniTaskAsyncEnumerable<T1> source1;
|
|
readonly IUniTaskAsyncEnumerable<T2> source2;
|
|
readonly IUniTaskAsyncEnumerable<T3> source3;
|
|
readonly IUniTaskAsyncEnumerable<T4> source4;
|
|
readonly IUniTaskAsyncEnumerable<T5> source5;
|
|
readonly IUniTaskAsyncEnumerable<T6> source6;
|
|
readonly IUniTaskAsyncEnumerable<T7> source7;
|
|
readonly IUniTaskAsyncEnumerable<T8> source8;
|
|
readonly IUniTaskAsyncEnumerable<T9> source9;
|
|
readonly IUniTaskAsyncEnumerable<T10> source10;
|
|
readonly IUniTaskAsyncEnumerable<T11> source11;
|
|
readonly IUniTaskAsyncEnumerable<T12> source12;
|
|
readonly IUniTaskAsyncEnumerable<T13> source13;
|
|
readonly IUniTaskAsyncEnumerable<T14> source14;
|
|
readonly IUniTaskAsyncEnumerable<T15> source15;
|
|
|
|
readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult> resultSelector;
|
|
|
|
public CombineLatest(IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, IUniTaskAsyncEnumerable<T7> source7, IUniTaskAsyncEnumerable<T8> source8, IUniTaskAsyncEnumerable<T9> source9, IUniTaskAsyncEnumerable<T10> source10, IUniTaskAsyncEnumerable<T11> source11, IUniTaskAsyncEnumerable<T12> source12, IUniTaskAsyncEnumerable<T13> source13, IUniTaskAsyncEnumerable<T14> source14, IUniTaskAsyncEnumerable<T15> source15, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult> resultSelector)
|
|
{
|
|
this.source1 = source1;
|
|
this.source2 = source2;
|
|
this.source3 = source3;
|
|
this.source4 = source4;
|
|
this.source5 = source5;
|
|
this.source6 = source6;
|
|
this.source7 = source7;
|
|
this.source8 = source8;
|
|
this.source9 = source9;
|
|
this.source10 = source10;
|
|
this.source11 = source11;
|
|
this.source12 = source12;
|
|
this.source13 = source13;
|
|
this.source14 = source14;
|
|
this.source15 = source15;
|
|
|
|
this.resultSelector = resultSelector;
|
|
}
|
|
|
|
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
|
{
|
|
return new _CombineLatest(source1, source2, source3, source4, source5, source6, source7, source8, source9, source10, source11, source12, source13, source14, source15, resultSelector, cancellationToken);
|
|
}
|
|
|
|
class _CombineLatest : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
|
|
{
|
|
static readonly Action<object> Completed1Delegate = Completed1;
|
|
static readonly Action<object> Completed2Delegate = Completed2;
|
|
static readonly Action<object> Completed3Delegate = Completed3;
|
|
static readonly Action<object> Completed4Delegate = Completed4;
|
|
static readonly Action<object> Completed5Delegate = Completed5;
|
|
static readonly Action<object> Completed6Delegate = Completed6;
|
|
static readonly Action<object> Completed7Delegate = Completed7;
|
|
static readonly Action<object> Completed8Delegate = Completed8;
|
|
static readonly Action<object> Completed9Delegate = Completed9;
|
|
static readonly Action<object> Completed10Delegate = Completed10;
|
|
static readonly Action<object> Completed11Delegate = Completed11;
|
|
static readonly Action<object> Completed12Delegate = Completed12;
|
|
static readonly Action<object> Completed13Delegate = Completed13;
|
|
static readonly Action<object> Completed14Delegate = Completed14;
|
|
static readonly Action<object> Completed15Delegate = Completed15;
|
|
const int CompleteCount = 15;
|
|
|
|
readonly IUniTaskAsyncEnumerable<T1> source1;
|
|
readonly IUniTaskAsyncEnumerable<T2> source2;
|
|
readonly IUniTaskAsyncEnumerable<T3> source3;
|
|
readonly IUniTaskAsyncEnumerable<T4> source4;
|
|
readonly IUniTaskAsyncEnumerable<T5> source5;
|
|
readonly IUniTaskAsyncEnumerable<T6> source6;
|
|
readonly IUniTaskAsyncEnumerable<T7> source7;
|
|
readonly IUniTaskAsyncEnumerable<T8> source8;
|
|
readonly IUniTaskAsyncEnumerable<T9> source9;
|
|
readonly IUniTaskAsyncEnumerable<T10> source10;
|
|
readonly IUniTaskAsyncEnumerable<T11> source11;
|
|
readonly IUniTaskAsyncEnumerable<T12> source12;
|
|
readonly IUniTaskAsyncEnumerable<T13> source13;
|
|
readonly IUniTaskAsyncEnumerable<T14> source14;
|
|
readonly IUniTaskAsyncEnumerable<T15> source15;
|
|
|
|
readonly Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult> resultSelector;
|
|
CancellationToken cancellationToken;
|
|
|
|
IUniTaskAsyncEnumerator<T1> enumerator1;
|
|
UniTask<bool>.Awaiter awaiter1;
|
|
bool hasCurrent1;
|
|
bool running1;
|
|
T1 current1;
|
|
|
|
IUniTaskAsyncEnumerator<T2> enumerator2;
|
|
UniTask<bool>.Awaiter awaiter2;
|
|
bool hasCurrent2;
|
|
bool running2;
|
|
T2 current2;
|
|
|
|
IUniTaskAsyncEnumerator<T3> enumerator3;
|
|
UniTask<bool>.Awaiter awaiter3;
|
|
bool hasCurrent3;
|
|
bool running3;
|
|
T3 current3;
|
|
|
|
IUniTaskAsyncEnumerator<T4> enumerator4;
|
|
UniTask<bool>.Awaiter awaiter4;
|
|
bool hasCurrent4;
|
|
bool running4;
|
|
T4 current4;
|
|
|
|
IUniTaskAsyncEnumerator<T5> enumerator5;
|
|
UniTask<bool>.Awaiter awaiter5;
|
|
bool hasCurrent5;
|
|
bool running5;
|
|
T5 current5;
|
|
|
|
IUniTaskAsyncEnumerator<T6> enumerator6;
|
|
UniTask<bool>.Awaiter awaiter6;
|
|
bool hasCurrent6;
|
|
bool running6;
|
|
T6 current6;
|
|
|
|
IUniTaskAsyncEnumerator<T7> enumerator7;
|
|
UniTask<bool>.Awaiter awaiter7;
|
|
bool hasCurrent7;
|
|
bool running7;
|
|
T7 current7;
|
|
|
|
IUniTaskAsyncEnumerator<T8> enumerator8;
|
|
UniTask<bool>.Awaiter awaiter8;
|
|
bool hasCurrent8;
|
|
bool running8;
|
|
T8 current8;
|
|
|
|
IUniTaskAsyncEnumerator<T9> enumerator9;
|
|
UniTask<bool>.Awaiter awaiter9;
|
|
bool hasCurrent9;
|
|
bool running9;
|
|
T9 current9;
|
|
|
|
IUniTaskAsyncEnumerator<T10> enumerator10;
|
|
UniTask<bool>.Awaiter awaiter10;
|
|
bool hasCurrent10;
|
|
bool running10;
|
|
T10 current10;
|
|
|
|
IUniTaskAsyncEnumerator<T11> enumerator11;
|
|
UniTask<bool>.Awaiter awaiter11;
|
|
bool hasCurrent11;
|
|
bool running11;
|
|
T11 current11;
|
|
|
|
IUniTaskAsyncEnumerator<T12> enumerator12;
|
|
UniTask<bool>.Awaiter awaiter12;
|
|
bool hasCurrent12;
|
|
bool running12;
|
|
T12 current12;
|
|
|
|
IUniTaskAsyncEnumerator<T13> enumerator13;
|
|
UniTask<bool>.Awaiter awaiter13;
|
|
bool hasCurrent13;
|
|
bool running13;
|
|
T13 current13;
|
|
|
|
IUniTaskAsyncEnumerator<T14> enumerator14;
|
|
UniTask<bool>.Awaiter awaiter14;
|
|
bool hasCurrent14;
|
|
bool running14;
|
|
T14 current14;
|
|
|
|
IUniTaskAsyncEnumerator<T15> enumerator15;
|
|
UniTask<bool>.Awaiter awaiter15;
|
|
bool hasCurrent15;
|
|
bool running15;
|
|
T15 current15;
|
|
|
|
int completedCount;
|
|
bool syncRunning;
|
|
TResult result;
|
|
|
|
public _CombineLatest(IUniTaskAsyncEnumerable<T1> source1, IUniTaskAsyncEnumerable<T2> source2, IUniTaskAsyncEnumerable<T3> source3, IUniTaskAsyncEnumerable<T4> source4, IUniTaskAsyncEnumerable<T5> source5, IUniTaskAsyncEnumerable<T6> source6, IUniTaskAsyncEnumerable<T7> source7, IUniTaskAsyncEnumerable<T8> source8, IUniTaskAsyncEnumerable<T9> source9, IUniTaskAsyncEnumerable<T10> source10, IUniTaskAsyncEnumerable<T11> source11, IUniTaskAsyncEnumerable<T12> source12, IUniTaskAsyncEnumerable<T13> source13, IUniTaskAsyncEnumerable<T14> source14, IUniTaskAsyncEnumerable<T15> source15, Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TResult> resultSelector, CancellationToken cancellationToken)
|
|
{
|
|
this.source1 = source1;
|
|
this.source2 = source2;
|
|
this.source3 = source3;
|
|
this.source4 = source4;
|
|
this.source5 = source5;
|
|
this.source6 = source6;
|
|
this.source7 = source7;
|
|
this.source8 = source8;
|
|
this.source9 = source9;
|
|
this.source10 = source10;
|
|
this.source11 = source11;
|
|
this.source12 = source12;
|
|
this.source13 = source13;
|
|
this.source14 = source14;
|
|
this.source15 = source15;
|
|
|
|
this.resultSelector = resultSelector;
|
|
this.cancellationToken = cancellationToken;
|
|
TaskTracker.TrackActiveTask(this, 3);
|
|
}
|
|
|
|
public TResult Current => result;
|
|
|
|
public UniTask<bool> MoveNextAsync()
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
if (completedCount == CompleteCount) return CompletedTasks.False;
|
|
|
|
if (enumerator1 == null)
|
|
{
|
|
enumerator1 = source1.GetAsyncEnumerator(cancellationToken);
|
|
enumerator2 = source2.GetAsyncEnumerator(cancellationToken);
|
|
enumerator3 = source3.GetAsyncEnumerator(cancellationToken);
|
|
enumerator4 = source4.GetAsyncEnumerator(cancellationToken);
|
|
enumerator5 = source5.GetAsyncEnumerator(cancellationToken);
|
|
enumerator6 = source6.GetAsyncEnumerator(cancellationToken);
|
|
enumerator7 = source7.GetAsyncEnumerator(cancellationToken);
|
|
enumerator8 = source8.GetAsyncEnumerator(cancellationToken);
|
|
enumerator9 = source9.GetAsyncEnumerator(cancellationToken);
|
|
enumerator10 = source10.GetAsyncEnumerator(cancellationToken);
|
|
enumerator11 = source11.GetAsyncEnumerator(cancellationToken);
|
|
enumerator12 = source12.GetAsyncEnumerator(cancellationToken);
|
|
enumerator13 = source13.GetAsyncEnumerator(cancellationToken);
|
|
enumerator14 = source14.GetAsyncEnumerator(cancellationToken);
|
|
enumerator15 = source15.GetAsyncEnumerator(cancellationToken);
|
|
}
|
|
|
|
completionSource.Reset();
|
|
|
|
AGAIN:
|
|
syncRunning = true;
|
|
if (!running1)
|
|
{
|
|
running1 = true;
|
|
awaiter1 = enumerator1.MoveNextAsync().GetAwaiter();
|
|
if (awaiter1.IsCompleted)
|
|
{
|
|
Completed1(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter1.SourceOnCompleted(Completed1Delegate, this);
|
|
}
|
|
}
|
|
if (!running2)
|
|
{
|
|
running2 = true;
|
|
awaiter2 = enumerator2.MoveNextAsync().GetAwaiter();
|
|
if (awaiter2.IsCompleted)
|
|
{
|
|
Completed2(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter2.SourceOnCompleted(Completed2Delegate, this);
|
|
}
|
|
}
|
|
if (!running3)
|
|
{
|
|
running3 = true;
|
|
awaiter3 = enumerator3.MoveNextAsync().GetAwaiter();
|
|
if (awaiter3.IsCompleted)
|
|
{
|
|
Completed3(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter3.SourceOnCompleted(Completed3Delegate, this);
|
|
}
|
|
}
|
|
if (!running4)
|
|
{
|
|
running4 = true;
|
|
awaiter4 = enumerator4.MoveNextAsync().GetAwaiter();
|
|
if (awaiter4.IsCompleted)
|
|
{
|
|
Completed4(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter4.SourceOnCompleted(Completed4Delegate, this);
|
|
}
|
|
}
|
|
if (!running5)
|
|
{
|
|
running5 = true;
|
|
awaiter5 = enumerator5.MoveNextAsync().GetAwaiter();
|
|
if (awaiter5.IsCompleted)
|
|
{
|
|
Completed5(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter5.SourceOnCompleted(Completed5Delegate, this);
|
|
}
|
|
}
|
|
if (!running6)
|
|
{
|
|
running6 = true;
|
|
awaiter6 = enumerator6.MoveNextAsync().GetAwaiter();
|
|
if (awaiter6.IsCompleted)
|
|
{
|
|
Completed6(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter6.SourceOnCompleted(Completed6Delegate, this);
|
|
}
|
|
}
|
|
if (!running7)
|
|
{
|
|
running7 = true;
|
|
awaiter7 = enumerator7.MoveNextAsync().GetAwaiter();
|
|
if (awaiter7.IsCompleted)
|
|
{
|
|
Completed7(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter7.SourceOnCompleted(Completed7Delegate, this);
|
|
}
|
|
}
|
|
if (!running8)
|
|
{
|
|
running8 = true;
|
|
awaiter8 = enumerator8.MoveNextAsync().GetAwaiter();
|
|
if (awaiter8.IsCompleted)
|
|
{
|
|
Completed8(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter8.SourceOnCompleted(Completed8Delegate, this);
|
|
}
|
|
}
|
|
if (!running9)
|
|
{
|
|
running9 = true;
|
|
awaiter9 = enumerator9.MoveNextAsync().GetAwaiter();
|
|
if (awaiter9.IsCompleted)
|
|
{
|
|
Completed9(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter9.SourceOnCompleted(Completed9Delegate, this);
|
|
}
|
|
}
|
|
if (!running10)
|
|
{
|
|
running10 = true;
|
|
awaiter10 = enumerator10.MoveNextAsync().GetAwaiter();
|
|
if (awaiter10.IsCompleted)
|
|
{
|
|
Completed10(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter10.SourceOnCompleted(Completed10Delegate, this);
|
|
}
|
|
}
|
|
if (!running11)
|
|
{
|
|
running11 = true;
|
|
awaiter11 = enumerator11.MoveNextAsync().GetAwaiter();
|
|
if (awaiter11.IsCompleted)
|
|
{
|
|
Completed11(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter11.SourceOnCompleted(Completed11Delegate, this);
|
|
}
|
|
}
|
|
if (!running12)
|
|
{
|
|
running12 = true;
|
|
awaiter12 = enumerator12.MoveNextAsync().GetAwaiter();
|
|
if (awaiter12.IsCompleted)
|
|
{
|
|
Completed12(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter12.SourceOnCompleted(Completed12Delegate, this);
|
|
}
|
|
}
|
|
if (!running13)
|
|
{
|
|
running13 = true;
|
|
awaiter13 = enumerator13.MoveNextAsync().GetAwaiter();
|
|
if (awaiter13.IsCompleted)
|
|
{
|
|
Completed13(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter13.SourceOnCompleted(Completed13Delegate, this);
|
|
}
|
|
}
|
|
if (!running14)
|
|
{
|
|
running14 = true;
|
|
awaiter14 = enumerator14.MoveNextAsync().GetAwaiter();
|
|
if (awaiter14.IsCompleted)
|
|
{
|
|
Completed14(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter14.SourceOnCompleted(Completed14Delegate, this);
|
|
}
|
|
}
|
|
if (!running15)
|
|
{
|
|
running15 = true;
|
|
awaiter15 = enumerator15.MoveNextAsync().GetAwaiter();
|
|
if (awaiter15.IsCompleted)
|
|
{
|
|
Completed15(this);
|
|
}
|
|
else
|
|
{
|
|
awaiter15.SourceOnCompleted(Completed15Delegate, this);
|
|
}
|
|
}
|
|
|
|
if (!running1 || !running2 || !running3 || !running4 || !running5 || !running6 || !running7 || !running8 || !running9 || !running10 || !running11 || !running12 || !running13 || !running14 || !running15)
|
|
{
|
|
goto AGAIN;
|
|
}
|
|
syncRunning = false;
|
|
|
|
return new UniTask<bool>(this, completionSource.Version);
|
|
}
|
|
|
|
static void Completed1(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running1 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter1.GetResult())
|
|
{
|
|
self.hasCurrent1 = true;
|
|
self.current1 = self.enumerator1.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running1 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter1 = self.enumerator1.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter1.SourceOnCompleted(Completed1Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed2(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running2 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter2.GetResult())
|
|
{
|
|
self.hasCurrent2 = true;
|
|
self.current2 = self.enumerator2.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running2 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter2 = self.enumerator2.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter2.SourceOnCompleted(Completed2Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed3(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running3 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter3.GetResult())
|
|
{
|
|
self.hasCurrent3 = true;
|
|
self.current3 = self.enumerator3.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running3 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter3 = self.enumerator3.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter3.SourceOnCompleted(Completed3Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed4(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running4 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter4.GetResult())
|
|
{
|
|
self.hasCurrent4 = true;
|
|
self.current4 = self.enumerator4.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running4 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter4 = self.enumerator4.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter4.SourceOnCompleted(Completed4Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed5(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running5 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter5.GetResult())
|
|
{
|
|
self.hasCurrent5 = true;
|
|
self.current5 = self.enumerator5.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running5 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter5 = self.enumerator5.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter5.SourceOnCompleted(Completed5Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed6(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running6 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter6.GetResult())
|
|
{
|
|
self.hasCurrent6 = true;
|
|
self.current6 = self.enumerator6.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running6 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter6 = self.enumerator6.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter6.SourceOnCompleted(Completed6Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed7(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running7 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter7.GetResult())
|
|
{
|
|
self.hasCurrent7 = true;
|
|
self.current7 = self.enumerator7.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running7 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running7 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running7 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter7 = self.enumerator7.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter7.SourceOnCompleted(Completed7Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed8(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running8 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter8.GetResult())
|
|
{
|
|
self.hasCurrent8 = true;
|
|
self.current8 = self.enumerator8.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running8 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running8 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running8 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter8 = self.enumerator8.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter8.SourceOnCompleted(Completed8Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed9(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running9 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter9.GetResult())
|
|
{
|
|
self.hasCurrent9 = true;
|
|
self.current9 = self.enumerator9.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running9 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running9 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running9 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter9 = self.enumerator9.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter9.SourceOnCompleted(Completed9Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed10(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running10 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter10.GetResult())
|
|
{
|
|
self.hasCurrent10 = true;
|
|
self.current10 = self.enumerator10.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running10 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running10 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running10 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter10 = self.enumerator10.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter10.SourceOnCompleted(Completed10Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed11(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running11 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter11.GetResult())
|
|
{
|
|
self.hasCurrent11 = true;
|
|
self.current11 = self.enumerator11.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running11 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running11 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running11 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter11 = self.enumerator11.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter11.SourceOnCompleted(Completed11Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed12(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running12 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter12.GetResult())
|
|
{
|
|
self.hasCurrent12 = true;
|
|
self.current12 = self.enumerator12.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running12 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running12 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running12 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter12 = self.enumerator12.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter12.SourceOnCompleted(Completed12Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed13(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running13 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter13.GetResult())
|
|
{
|
|
self.hasCurrent13 = true;
|
|
self.current13 = self.enumerator13.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running13 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running13 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running13 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter13 = self.enumerator13.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter13.SourceOnCompleted(Completed13Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed14(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running14 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter14.GetResult())
|
|
{
|
|
self.hasCurrent14 = true;
|
|
self.current14 = self.enumerator14.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running14 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running14 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running14 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter14 = self.enumerator14.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter14.SourceOnCompleted(Completed14Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
static void Completed15(object state)
|
|
{
|
|
var self = (_CombineLatest)state;
|
|
self.running15 = false;
|
|
|
|
try
|
|
{
|
|
if (self.awaiter15.GetResult())
|
|
{
|
|
self.hasCurrent15 = true;
|
|
self.current15 = self.enumerator15.Current;
|
|
goto SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
self.running15 = true; // as complete, no more call MoveNextAsync.
|
|
if (Interlocked.Increment(ref self.completedCount) == CompleteCount)
|
|
{
|
|
goto COMPLETE;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.running15 = true; // as complete, no more call MoveNextAsync.
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
SUCCESS:
|
|
if (!self.TrySetResult())
|
|
{
|
|
if (self.syncRunning) return;
|
|
self.running15 = true; // as complete, no more call MoveNextAsync.
|
|
try
|
|
{
|
|
self.awaiter15 = self.enumerator15.MoveNextAsync().GetAwaiter();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
self.completedCount = CompleteCount;
|
|
self.completionSource.TrySetException(ex);
|
|
return;
|
|
}
|
|
|
|
self.awaiter15.SourceOnCompleted(Completed15Delegate, self);
|
|
}
|
|
return;
|
|
COMPLETE:
|
|
self.completionSource.TrySetResult(false);
|
|
return;
|
|
}
|
|
|
|
bool TrySetResult()
|
|
{
|
|
if (hasCurrent1 && hasCurrent2 && hasCurrent3 && hasCurrent4 && hasCurrent5 && hasCurrent6 && hasCurrent7 && hasCurrent8 && hasCurrent9 && hasCurrent10 && hasCurrent11 && hasCurrent12 && hasCurrent13 && hasCurrent14 && hasCurrent15)
|
|
{
|
|
result = resultSelector(current1, current2, current3, current4, current5, current6, current7, current8, current9, current10, current11, current12, current13, current14, current15);
|
|
completionSource.TrySetResult(true);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async UniTask DisposeAsync()
|
|
{
|
|
TaskTracker.RemoveTracking(this);
|
|
if (enumerator1 != null)
|
|
{
|
|
await enumerator1.DisposeAsync();
|
|
}
|
|
if (enumerator2 != null)
|
|
{
|
|
await enumerator2.DisposeAsync();
|
|
}
|
|
if (enumerator3 != null)
|
|
{
|
|
await enumerator3.DisposeAsync();
|
|
}
|
|
if (enumerator4 != null)
|
|
{
|
|
await enumerator4.DisposeAsync();
|
|
}
|
|
if (enumerator5 != null)
|
|
{
|
|
await enumerator5.DisposeAsync();
|
|
}
|
|
if (enumerator6 != null)
|
|
{
|
|
await enumerator6.DisposeAsync();
|
|
}
|
|
if (enumerator7 != null)
|
|
{
|
|
await enumerator7.DisposeAsync();
|
|
}
|
|
if (enumerator8 != null)
|
|
{
|
|
await enumerator8.DisposeAsync();
|
|
}
|
|
if (enumerator9 != null)
|
|
{
|
|
await enumerator9.DisposeAsync();
|
|
}
|
|
if (enumerator10 != null)
|
|
{
|
|
await enumerator10.DisposeAsync();
|
|
}
|
|
if (enumerator11 != null)
|
|
{
|
|
await enumerator11.DisposeAsync();
|
|
}
|
|
if (enumerator12 != null)
|
|
{
|
|
await enumerator12.DisposeAsync();
|
|
}
|
|
if (enumerator13 != null)
|
|
{
|
|
await enumerator13.DisposeAsync();
|
|
}
|
|
if (enumerator14 != null)
|
|
{
|
|
await enumerator14.DisposeAsync();
|
|
}
|
|
if (enumerator15 != null)
|
|
{
|
|
await enumerator15.DisposeAsync();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
} |