You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
11372 lines
431 KiB
11372 lines
431 KiB
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(); |
|
} |
|
} |
|
} |
|
} |
|
|
|
} |