start to implements async linq

master
neuecc 2020-05-08 03:23:14 +09:00
parent be45066773
commit 61b798b6e9
70 changed files with 43940 additions and 45 deletions

View File

@ -0,0 +1,20 @@
using System.Threading;
namespace Cysharp.Threading.Tasks
{
public interface IUniTaskAsyncEnumerable<out T>
{
IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default);
}
public interface IUniTaskAsyncEnumerator<out T> : IUniTaskAsyncDisposable
{
T Current { get; }
UniTask<bool> MoveNextAsync();
}
public interface IUniTaskAsyncDisposable
{
UniTask DisposeAsync();
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class All
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class Any
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class Append
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class AsEnumerable
{
}
}

View File

@ -0,0 +1,357 @@
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public abstract class MoveNextSource : IUniTaskSource<bool>
{
protected UniTaskCompletionSourceCore<bool> completionSource;
public bool GetResult(short token)
{
return completionSource.GetResult(token);
}
public UniTaskStatus GetStatus(short token)
{
return completionSource.GetStatus(token);
}
public void OnCompleted(Action<object> continuation, object state, short token)
{
completionSource.OnCompleted(continuation, state, token);
}
public UniTaskStatus UnsafeGetStatus()
{
return completionSource.UnsafeGetStatus();
}
void IUniTaskSource.GetResult(short token)
{
completionSource.GetResult(token);
}
}
public abstract class AsyncEnumeratorBase<TSource, TResult> : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
{
static readonly Action<object> moveNextCallbackDelegate = MoveNextCallBack;
readonly IUniTaskAsyncEnumerable<TSource> source;
protected CancellationToken cancellationToken;
IUniTaskAsyncEnumerator<TSource> enumerator;
UniTask<bool>.Awaiter sourceMoveNext;
public AsyncEnumeratorBase(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
{
this.source = source;
this.cancellationToken = cancellationToken;
}
// abstract
/// <summary>
/// If return value is false, continue source.MoveNext.
/// </summary>
protected abstract bool TryMoveNextCore(bool sourceHasCurrent, out bool result);
// Util
protected TSource SourceCurrent => enumerator.Current;
// IUniTaskAsyncEnumerator<T>
public TResult Current { get; protected set; }
public UniTask<bool> MoveNextAsync()
{
if (enumerator == null)
{
enumerator = source.GetAsyncEnumerator(cancellationToken);
}
completionSource.Reset();
SourceMoveNext();
return new UniTask<bool>(this, completionSource.Version);
}
protected void SourceMoveNext()
{
CONTINUE:
sourceMoveNext = enumerator.MoveNextAsync().GetAwaiter();
if (sourceMoveNext.IsCompleted)
{
bool result = false;
try
{
if (!TryMoveNextCore(sourceMoveNext.GetResult(), out result))
{
goto CONTINUE;
}
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
if (cancellationToken.IsCancellationRequested)
{
completionSource.TrySetCanceled(cancellationToken);
}
else
{
completionSource.TrySetResult(result);
}
}
else
{
sourceMoveNext.SourceOnCompleted(moveNextCallbackDelegate, this);
}
}
static void MoveNextCallBack(object state)
{
var self = (AsyncEnumeratorBase<TSource, TResult>)state;
bool result;
try
{
if (!self.TryMoveNextCore(self.sourceMoveNext.GetResult(), out result))
{
self.SourceMoveNext();
return;
}
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
return;
}
if (self.cancellationToken.IsCancellationRequested)
{
self.completionSource.TrySetCanceled(self.cancellationToken);
}
else
{
self.completionSource.TrySetResult(result);
}
}
// if require additional resource to dispose, override and call base.DisposeAsync.
public virtual UniTask DisposeAsync()
{
if (enumerator != null)
{
return enumerator.DisposeAsync();
}
return default;
}
}
public abstract class AsyncEnumeratorAwaitSelectorBase<TSource, TResult, TAwait> : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
{
static readonly Action<object> moveNextCallbackDelegate = MoveNextCallBack;
readonly IUniTaskAsyncEnumerable<TSource> source;
protected CancellationToken cancellationToken;
IUniTaskAsyncEnumerator<TSource> enumerator;
UniTask<bool>.Awaiter sourceMoveNext;
UniTask<TAwait>.Awaiter resultAwaiter;
public AsyncEnumeratorAwaitSelectorBase(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
{
this.source = source;
this.cancellationToken = cancellationToken;
}
// abstract
protected abstract UniTask<TAwait> TransformAsync(TSource sourceCurrent);
protected abstract bool TrySetCurrentCore(TAwait awaitResult);
// Util
protected TSource SourceCurrent => enumerator.Current;
protected (bool waitCallback, bool requireNextIteration) ActionCompleted(bool trySetCurrentResult, out bool moveNextResult)
{
if (trySetCurrentResult)
{
moveNextResult = true;
return (false, false);
}
else
{
moveNextResult = default;
return (false, true);
}
}
protected (bool waitCallback, bool requireNextIteration) WaitAwaitCallback(out bool moveNextResult) { moveNextResult = default; return (true, false); }
protected (bool waitCallback, bool requireNextIteration) IterateFinished(out bool moveNextResult) { moveNextResult = false; return (false, false); }
// IUniTaskAsyncEnumerator<T>
public TResult Current { get; protected set; }
public UniTask<bool> MoveNextAsync()
{
if (enumerator == null)
{
enumerator = source.GetAsyncEnumerator(cancellationToken);
}
completionSource.Reset();
SourceMoveNext();
return new UniTask<bool>(this, completionSource.Version);
}
protected void SourceMoveNext()
{
CONTINUE:
sourceMoveNext = enumerator.MoveNextAsync().GetAwaiter();
if (sourceMoveNext.IsCompleted)
{
bool result = false;
try
{
(bool waitCallback, bool requireNextIteration) = TryMoveNextCore(sourceMoveNext.GetResult(), out result);
if (waitCallback)
{
return;
}
if (requireNextIteration)
{
goto CONTINUE;
}
else
{
completionSource.TrySetResult(result);
}
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
}
else
{
sourceMoveNext.SourceOnCompleted(moveNextCallbackDelegate, this);
}
}
(bool waitCallback, bool requireNextIteration) TryMoveNextCore(bool sourceHasCurrent, out bool result)
{
if (sourceHasCurrent)
{
var task = TransformAsync(enumerator.Current);
if (UnwarapTask(task, out var taskResult))
{
return ActionCompleted(TrySetCurrentCore(taskResult), out result);
}
else
{
return WaitAwaitCallback(out result);
}
}
return IterateFinished(out result);
}
protected bool UnwarapTask(UniTask<TAwait> taskResult, out TAwait result)
{
resultAwaiter = taskResult.GetAwaiter();
if (resultAwaiter.IsCompleted)
{
result = resultAwaiter.GetResult();
return true;
}
else
{
resultAwaiter.SourceOnCompleted(SetCurrentCallBack, this); // TODO:cache
result = default;
return false;
}
}
static void MoveNextCallBack(object state)
{
var self = (AsyncEnumeratorAwaitSelectorBase<TSource, TResult, TAwait>)state;
bool result = false;
try
{
(bool waitCallback, bool requireNextIteration) = self.TryMoveNextCore(self.sourceMoveNext.GetResult(), out result);
if (waitCallback)
{
return;
}
if (requireNextIteration)
{
self.SourceMoveNext();
return;
}
else
{
self.completionSource.TrySetResult(result);
}
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
return;
}
}
static void SetCurrentCallBack(object state)
{
var self = (AsyncEnumeratorAwaitSelectorBase<TSource, TResult, TAwait>)state;
bool doneSetCurrent;
try
{
var result = self.resultAwaiter.GetResult();
doneSetCurrent = self.TrySetCurrentCore(result);
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
return;
}
if (self.cancellationToken.IsCancellationRequested)
{
self.completionSource.TrySetCanceled(self.cancellationToken);
}
else
{
if (doneSetCurrent)
{
self.completionSource.TrySetResult(true);
}
else
{
self.SourceMoveNext();
}
}
}
// if require additional resource to dispose, override and call base.DisposeAsync.
public virtual UniTask DisposeAsync()
{
if (enumerator != null)
{
return enumerator.DisposeAsync();
}
return default;
}
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class Average
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class Cast
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class Concat
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class Contains
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class Count
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class Create
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class DefaultIfEmpty
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class Distinct
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class ElementAt
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class ElementAtOrDefault
{
}
}

View File

@ -0,0 +1,48 @@
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<T> Empty<T>()
{
return Cysharp.Threading.Tasks.Linq.Empty<T>.Instance;
}
}
internal class Empty<T> : IUniTaskAsyncEnumerable<T>
{
public static readonly IUniTaskAsyncEnumerable<T> Instance = new Empty<T>();
Empty()
{
}
public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
return Enumerator.Instance;
}
class Enumerator : IUniTaskAsyncEnumerator<T>
{
public static readonly IUniTaskAsyncEnumerator<T> Instance = new Enumerator();
Enumerator()
{
}
public T Current => default;
public UniTask<bool> MoveNextAsync()
{
return CompletedTasks.False;
}
public UniTask DisposeAsync()
{
return default;
}
}
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class Except
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class First
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class FirstOrDefault
{
}
}

View File

@ -0,0 +1,177 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static UniTask ForEachAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource> action, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(action, nameof(action));
return Cysharp.Threading.Tasks.Linq.ForEach<TSource>.InvokeAsync(source, action, cancellationToken);
}
public static UniTask ForEachAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource, Int32> action, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(action, nameof(action));
return Cysharp.Threading.Tasks.Linq.ForEach<TSource>.InvokeAsync(source, action, cancellationToken);
}
public static UniTask ForEachAwaitAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> action, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(action, nameof(action));
return Cysharp.Threading.Tasks.Linq.ForEach<TSource>.InvokeAwaitAsync(source, action, cancellationToken);
}
public static UniTask ForEachAwaitAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, UniTask> action, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(action, nameof(action));
return Cysharp.Threading.Tasks.Linq.ForEach<TSource>.InvokeAwaitAsync(source, action, cancellationToken);
}
public static UniTask ForEachAwaitWithCancellationAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask> action, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(action, nameof(action));
return Cysharp.Threading.Tasks.Linq.ForEach<TSource>.InvokeAwaitWithCancellationAsync(source, action, cancellationToken);
}
public static UniTask ForEachAwaitWithCancellationAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, CancellationToken, UniTask> action, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(action, nameof(action));
return Cysharp.Threading.Tasks.Linq.ForEach<TSource>.InvokeAwaitWithCancellationAsync(source, action, cancellationToken);
}
}
internal static class ForEach<TSource>
{
public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable<TSource> source, Action<TSource> action, CancellationToken cancellationToken)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
action(e.Current);
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable<TSource> source, Action<TSource, Int32> action, CancellationToken cancellationToken)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
int index = 0;
while (await e.MoveNextAsync())
{
action(e.Current, checked(index++));
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
public static async UniTask InvokeAwaitAsync(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> action, CancellationToken cancellationToken)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
await action(e.Current);
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
public static async UniTask InvokeAwaitAsync(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, UniTask> action, CancellationToken cancellationToken)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
int index = 0;
while (await e.MoveNextAsync())
{
await action(e.Current, checked(index++));
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
public static async UniTask InvokeAwaitWithCancellationAsync(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask> action, CancellationToken cancellationToken)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
await action(e.Current, cancellationToken);
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
public static async UniTask InvokeAwaitWithCancellationAsync(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, CancellationToken, UniTask> action, CancellationToken cancellationToken)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
int index = 0;
while (await e.MoveNextAsync())
{
await action(e.Current, checked(index++), cancellationToken);
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class GroupBy
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class GroupJoin
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class Intersect
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class Join
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class Last
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class LastOrDefault
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class LongCount
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class Max
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class Min
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class OfType
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class OrderBy
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class OrderByDescending
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class Prepend
{
}
}

View File

@ -0,0 +1,76 @@
using Cysharp.Threading.Tasks.Internal;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<int> Range(int start, int count)
{
if (count < 0) throw Error.ArgumentOutOfRange(nameof(count));
var end = (long)start + count - 1L;
if (end > int.MaxValue) throw Error.ArgumentOutOfRange(nameof(count));
if (count == 0) UniTaskAsyncEnumerable.Empty<int>();
return new Cysharp.Threading.Tasks.Linq.Range(start, count);
}
}
internal class Range : IUniTaskAsyncEnumerable<int>
{
readonly int start;
readonly int end;
public Range(int start, int count)
{
this.start = start;
this.end = start + count;
}
public IUniTaskAsyncEnumerator<int> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
return new Enumerator(start, end, cancellationToken);
}
class Enumerator : IUniTaskAsyncEnumerator<int>
{
readonly int start;
readonly int end;
int current;
CancellationToken cancellationToken;
public Enumerator(int start, int end, CancellationToken cancellationToken)
{
this.start = start;
this.end = end;
this.cancellationToken = cancellationToken;
this.current = 0;
}
public int Current => current;
public UniTask<bool> MoveNextAsync()
{
if (cancellationToken.IsCancellationRequested) return CompletedTasks.False;
current++;
if (current != end)
{
return CompletedTasks.True;
}
return CompletedTasks.False;
}
public UniTask DisposeAsync()
{
return default;
}
}
}
}

View File

@ -0,0 +1,69 @@
using Cysharp.Threading.Tasks.Internal;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TResult> Repeat<TResult>(TResult element, int count)
{
if (count < 0) throw Error.ArgumentOutOfRange(nameof(count));
return new Repeat<TResult>(element, count);
}
}
internal class Repeat<TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly TResult element;
readonly int count;
public Repeat(TResult element, int count)
{
this.element = element;
this.count = count;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
return new Enumerator(element, count, cancellationToken);
}
class Enumerator : IUniTaskAsyncEnumerator<TResult>
{
readonly TResult element;
readonly int count;
int remaining;
CancellationToken cancellationToken;
public Enumerator(TResult element, int count, CancellationToken cancellationToken)
{
this.element = element;
this.count = count;
this.cancellationToken = cancellationToken;
this.remaining = count;
}
public TResult Current => element;
public UniTask<bool> MoveNextAsync()
{
if (cancellationToken.IsCancellationRequested) return CompletedTasks.False;
if (remaining-- != 0)
{
return CompletedTasks.True;
}
return CompletedTasks.False;
}
public UniTask DisposeAsync()
{
return default;
}
}
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class Reverse
{
}
}

View File

@ -0,0 +1,309 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TResult> Select<TSource, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TResult> selector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(selector, nameof(selector));
return new Cysharp.Threading.Tasks.Linq.Select<TSource, TResult>(source, selector);
}
public static IUniTaskAsyncEnumerable<TResult> Select<TSource, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, TResult> selector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(selector, nameof(selector));
return new Cysharp.Threading.Tasks.Linq.SelectInt<TSource, TResult>(source, selector);
}
public static IUniTaskAsyncEnumerable<TResult> SelectAwait<TSource, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TResult>> selector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(selector, nameof(selector));
return new Cysharp.Threading.Tasks.Linq.SelectAwait<TSource, TResult>(source, selector);
}
public static IUniTaskAsyncEnumerable<TResult> SelectAwait<TSource, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, UniTask<TResult>> selector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(selector, nameof(selector));
return new Cysharp.Threading.Tasks.Linq.SelectAwaitInt<TSource, TResult>(source, selector);
}
public static IUniTaskAsyncEnumerable<TResult> SelectAwaitWithCancellation<TSource, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TResult>> selector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(selector, nameof(selector));
return new Cysharp.Threading.Tasks.Linq.SelectAwaitCancellation<TSource, TResult>(source, selector);
}
public static IUniTaskAsyncEnumerable<TResult> SelectAwaitWithCancellation<TSource, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, CancellationToken, UniTask<TResult>> selector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(selector, nameof(selector));
return new Cysharp.Threading.Tasks.Linq.SelectAwaitIntCancellation<TSource, TResult>(source, selector);
}
}
internal sealed class Select<TSource, TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, TResult> selector;
public Select(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TResult> selector)
{
this.source = source;
this.selector = selector;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
return new Enumerator(source, selector, cancellationToken);
}
sealed class Enumerator : AsyncEnumeratorBase<TSource, TResult>
{
readonly Func<TSource, TResult> selector;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TResult> selector, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.selector = selector;
}
protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result)
{
if (sourceHasCurrent)
{
Current = selector(SourceCurrent);
result = true;
return true;
}
else
{
result = false;
return true;
}
}
}
}
internal sealed class SelectInt<TSource, TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, int, TResult> selector;
public SelectInt(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, TResult> selector)
{
this.source = source;
this.selector = selector;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
return new Enumerator(source, selector, cancellationToken);
}
sealed class Enumerator : AsyncEnumeratorBase<TSource, TResult>
{
readonly Func<TSource, int, TResult> selector;
int index;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, TResult> selector, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.selector = selector;
}
protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result)
{
if (sourceHasCurrent)
{
Current = selector(SourceCurrent, checked(index++));
result = true;
return true;
}
else
{
result = false;
return true;
}
}
}
}
internal sealed class SelectAwait<TSource, TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, UniTask<TResult>> selector;
public SelectAwait(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TResult>> selector)
{
this.source = source;
this.selector = selector;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
return new Enumerator(source, selector, cancellationToken);
}
sealed class Enumerator : AsyncEnumeratorAwaitSelectorBase<TSource, TResult, TResult>
{
readonly Func<TSource, UniTask<TResult>> selector;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TResult>> selector, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.selector = selector;
}
protected override UniTask<TResult> TransformAsync(TSource sourceCurrent)
{
return selector(sourceCurrent);
}
protected override bool TrySetCurrentCore(TResult awaitResult)
{
Current = awaitResult;
return true;
}
}
}
internal sealed class SelectAwaitInt<TSource, TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, int, UniTask<TResult>> selector;
public SelectAwaitInt(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, UniTask<TResult>> selector)
{
this.source = source;
this.selector = selector;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
return new Enumerator(source, selector, cancellationToken);
}
sealed class Enumerator : AsyncEnumeratorAwaitSelectorBase<TSource, TResult, TResult>
{
readonly Func<TSource, int, UniTask<TResult>> selector;
int index;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, UniTask<TResult>> selector, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.selector = selector;
}
protected override UniTask<TResult> TransformAsync(TSource sourceCurrent)
{
return selector(sourceCurrent, checked(index++));
}
protected override bool TrySetCurrentCore(TResult awaitResult)
{
Current = awaitResult;
return true;
}
}
}
internal sealed class SelectAwaitCancellation<TSource, TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, CancellationToken, UniTask<TResult>> selector;
public SelectAwaitCancellation(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TResult>> selector)
{
this.source = source;
this.selector = selector;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
return new Enumerator(source, selector, cancellationToken);
}
sealed class Enumerator : AsyncEnumeratorAwaitSelectorBase<TSource, TResult, TResult>
{
readonly Func<TSource, CancellationToken, UniTask<TResult>> selector;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TResult>> selector, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.selector = selector;
}
protected override UniTask<TResult> TransformAsync(TSource sourceCurrent)
{
return selector(sourceCurrent, cancellationToken);
}
protected override bool TrySetCurrentCore(TResult awaitResult)
{
Current = awaitResult;
return true;
}
}
}
internal sealed class SelectAwaitIntCancellation<TSource, TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, int, CancellationToken, UniTask<TResult>> selector;
public SelectAwaitIntCancellation(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, CancellationToken, UniTask<TResult>> selector)
{
this.source = source;
this.selector = selector;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
return new Enumerator(source, selector, cancellationToken);
}
sealed class Enumerator : AsyncEnumeratorAwaitSelectorBase<TSource, TResult, TResult>
{
readonly Func<TSource, int, CancellationToken, UniTask<TResult>> selector;
int index;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, CancellationToken, UniTask<TResult>> selector, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.selector = selector;
}
protected override UniTask<TResult> TransformAsync(TSource sourceCurrent)
{
return selector(sourceCurrent, checked(index++), cancellationToken);
}
protected override bool TrySetCurrentCore(TResult awaitResult)
{
Current = awaitResult;
return true;
}
}
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class SelectMany
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class SequenceEqual
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class Single
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class SingleOrDefault
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class Skip
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class SkipLast
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class SkipWhile
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class Sum
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class Take
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class TakeLast
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class TakeWhile
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class ThenBy
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class ThenByDescending
{
}
}

View File

@ -0,0 +1,57 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Collections.Generic;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static UniTask<TSource[]> ToArrayAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken = default)
{
return Cysharp.Threading.Tasks.Linq.ToArray<TSource>.InvokeAsync(source, cancellationToken);
}
}
internal static class ToArray<TSource>
{
internal static async UniTask<TSource[]> InvokeAsync(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
{
var pool = ArrayPool<TSource>.Shared;
var array = pool.Rent(16);
TSource[] result = default;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
var i = 0;
while (await e.MoveNextAsync())
{
ArrayPoolUtil.EnsureCapacity(ref array, i, pool);
array[i++] = e.Current;
}
if (i == 0)
{
result = Array.Empty<TSource>();
}
else
{
result = new TSource[i];
Array.Copy(array, result, i);
}
}
finally
{
pool.Return(array, clearArray: !RuntimeHelpersAbstraction.IsWellKnownNoReferenceContainsType<TSource>());
if (e != null)
{
await e.DisposeAsync();
}
}
return result;
}
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class ToDictionary
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class ToEnumerable
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class ToHashSet
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class ToList
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class ToLookup
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class ToObservable
{
}
}

View File

@ -0,0 +1,775 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class Union
{
}
}

View File

@ -0,0 +1,116 @@
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TSource> Where<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
{
return new Cysharp.Threading.Tasks.Linq.Where<TSource>(source, predicate);
}
public static IUniTaskAsyncEnumerable<TSource> WhereAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<bool>> predicate)
{
return new Cysharp.Threading.Tasks.Linq.WhereAwait<TSource>(source, predicate);
}
}
internal sealed class Where<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, bool> predicate;
public Where(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
{
this.source = source;
this.predicate = predicate;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, predicate, cancellationToken);
}
class Enumerator : AsyncEnumeratorBase<TSource, TSource>
{
readonly Func<TSource, bool> predicate;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.predicate = predicate;
}
protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result)
{
if (sourceHasCurrent)
{
if (predicate(SourceCurrent))
{
Current = SourceCurrent;
result = true;
return true;
}
else
{
result = default;
return false;
}
}
result = false;
return true;
}
}
}
internal sealed class WhereAwait<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, UniTask<bool>> predicate;
public WhereAwait(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<bool>> predicate)
{
this.source = source;
this.predicate = predicate;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, predicate, cancellationToken);
}
class Enumerator : AsyncEnumeratorAwaitSelectorBase<TSource, TSource, bool>
{
readonly Func<TSource, UniTask<bool>> predicate;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<bool>> predicate, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.predicate = predicate;
}
protected override UniTask<bool> TransformAsync(TSource sourceCurrent)
{
return predicate(sourceCurrent);
}
protected override bool TrySetCurrentCore(bool awaitResult)
{
if (awaitResult)
{
Current = SourceCurrent;
return true;
}
else
{
return false;
}
}
}
}
}

View File

@ -0,0 +1,308 @@
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<(TFirst First, TSecond Second)> Zip<TFirst, TSecond>(this IUniTaskAsyncEnumerable<TFirst> first, IUniTaskAsyncEnumerable<TSecond> second)
{
return Zip(first, second, (x, y) => (x, y));
}
public static IUniTaskAsyncEnumerable<TResult> Zip<TFirst, TSecond, TResult>(this IUniTaskAsyncEnumerable<TFirst> first, IUniTaskAsyncEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector)
{
return new Cysharp.Threading.Tasks.Linq.Zip<TFirst, TSecond, TResult>(first, second, resultSelector);
}
}
internal sealed class Zip<TFirst, TSecond, TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<TFirst> first;
readonly IUniTaskAsyncEnumerable<TSecond> second;
readonly Func<TFirst, TSecond, TResult> resultSelector;
public Zip(IUniTaskAsyncEnumerable<TFirst> first, IUniTaskAsyncEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector)
{
this.first = first;
this.second = second;
this.resultSelector = resultSelector;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(first, second, resultSelector, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
{
static readonly Action<object> firstMoveNextCoreDelegate = FirstMoveNextCore;
static readonly Action<object> secondMoveNextCoreDelegate = SecondMoveNextCore;
readonly IUniTaskAsyncEnumerable<TFirst> first;
readonly IUniTaskAsyncEnumerable<TSecond> second;
readonly Func<TFirst, TSecond, TResult> resultSelector;
CancellationToken cancellationToken;
IUniTaskAsyncEnumerator<TFirst> firstEnumerator;
IUniTaskAsyncEnumerator<TSecond> secondEnumerator;
UniTask<bool>.Awaiter firstAwaiter;
UniTask<bool>.Awaiter secondAwaiter;
public Enumerator(IUniTaskAsyncEnumerable<TFirst> first, IUniTaskAsyncEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector, CancellationToken cancellationToken)
{
this.first = first;
this.second = second;
this.resultSelector = resultSelector;
this.cancellationToken = cancellationToken;
}
public TResult Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
completionSource.Reset();
if (firstEnumerator == null)
{
firstEnumerator = first.GetAsyncEnumerator(cancellationToken);
secondEnumerator = second.GetAsyncEnumerator(cancellationToken);
}
firstAwaiter = firstEnumerator.MoveNextAsync().GetAwaiter();
if (firstAwaiter.IsCompleted)
{
FirstMoveNextCore(this);
}
else
{
firstAwaiter.SourceOnCompleted(firstMoveNextCoreDelegate, this);
}
return new UniTask<bool>(this, completionSource.Version);
}
static void FirstMoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.firstAwaiter.GetResult())
{
self.secondAwaiter = self.secondEnumerator.MoveNextAsync().GetAwaiter();
if (self.secondAwaiter.IsCompleted)
{
SecondMoveNextCore(self);
}
else
{
self.secondAwaiter.SourceOnCompleted(secondMoveNextCoreDelegate, self);
}
}
else
{
self.completionSource.TrySetResult(false);
}
}
static void SecondMoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.secondAwaiter.GetResult())
{
try
{
self.Current = self.resultSelector(self.firstEnumerator.Current, self.secondEnumerator.Current);
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
}
if (self.cancellationToken.IsCancellationRequested)
{
self.completionSource.TrySetCanceled(self.cancellationToken);
}
else
{
self.completionSource.TrySetResult(true);
}
}
else
{
self.completionSource.TrySetResult(false);
}
}
public async UniTask DisposeAsync()
{
if (firstEnumerator != null)
{
await firstEnumerator.DisposeAsync();
}
if (secondEnumerator != null)
{
await secondEnumerator.DisposeAsync();
}
}
}
}
internal sealed class ZipAwait<TFirst, TSecond, TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<TFirst> first;
readonly IUniTaskAsyncEnumerable<TSecond> second;
readonly Func<TFirst, TSecond, UniTask<TResult>> resultSelector;
public ZipAwait(IUniTaskAsyncEnumerable<TFirst> first, IUniTaskAsyncEnumerable<TSecond> second, Func<TFirst, TSecond, UniTask<TResult>> resultSelector)
{
this.first = first;
this.second = second;
this.resultSelector = resultSelector;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(first, second, resultSelector, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
{
static readonly Action<object> firstMoveNextCoreDelegate = FirstMoveNextCore;
static readonly Action<object> secondMoveNextCoreDelegate = SecondMoveNextCore;
static readonly Action<object> unwrapResultTaskDelegate = UnwrapResultTask;
readonly IUniTaskAsyncEnumerable<TFirst> first;
readonly IUniTaskAsyncEnumerable<TSecond> second;
readonly Func<TFirst, TSecond, UniTask<TResult>> resultSelector;
CancellationToken cancellationToken;
IUniTaskAsyncEnumerator<TFirst> firstEnumerator;
IUniTaskAsyncEnumerator<TSecond> secondEnumerator;
UniTask<bool>.Awaiter firstAwaiter;
UniTask<bool>.Awaiter secondAwaiter;
UniTask<TResult>.Awaiter resultAwaiter;
public Enumerator(IUniTaskAsyncEnumerable<TFirst> first, IUniTaskAsyncEnumerable<TSecond> second, Func<TFirst, TSecond, UniTask<TResult>> resultSelector, CancellationToken cancellationToken)
{
this.first = first;
this.second = second;
this.resultSelector = resultSelector;
this.cancellationToken = cancellationToken;
}
public TResult Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
completionSource.Reset();
if (firstEnumerator == null)
{
firstEnumerator = first.GetAsyncEnumerator(cancellationToken);
secondEnumerator = second.GetAsyncEnumerator(cancellationToken);
}
firstAwaiter = firstEnumerator.MoveNextAsync().GetAwaiter();
if (firstAwaiter.IsCompleted)
{
FirstMoveNextCore(this);
}
else
{
firstAwaiter.SourceOnCompleted(firstMoveNextCoreDelegate, this);
}
return new UniTask<bool>(this, completionSource.Version);
}
static void FirstMoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.firstAwaiter.GetResult())
{
self.secondAwaiter = self.secondEnumerator.MoveNextAsync().GetAwaiter();
if (self.secondAwaiter.IsCompleted)
{
SecondMoveNextCore(self);
}
else
{
self.secondAwaiter.SourceOnCompleted(secondMoveNextCoreDelegate, self);
}
}
else
{
self.completionSource.TrySetResult(false);
}
}
static void SecondMoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.secondAwaiter.GetResult())
{
var task = self.resultSelector(self.firstEnumerator.Current, self.secondEnumerator.Current);
self.resultAwaiter = task.GetAwaiter();
if (self.resultAwaiter.IsCompleted)
{
UnwrapResultTask(self);
}
else
{
self.resultAwaiter.SourceOnCompleted(unwrapResultTaskDelegate, self);
}
}
else
{
self.completionSource.TrySetResult(false);
}
}
static void UnwrapResultTask(object state)
{
var self = (Enumerator)state;
try
{
self.Current = self.resultAwaiter.GetResult();
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
}
if (self.cancellationToken.IsCancellationRequested)
{
self.completionSource.TrySetCanceled(self.cancellationToken);
}
else
{
self.completionSource.TrySetResult(true);
}
}
public async UniTask DisposeAsync()
{
if (firstEnumerator != null)
{
await firstEnumerator.DisposeAsync();
}
if (secondEnumerator != null)
{
await secondEnumerator.DisposeAsync();
}
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -7,25 +7,7 @@
</PropertyGroup>
<ItemGroup>
<Compile Include="..\UniTask\Assets\Plugins\UniTask\**\*.cs"
Exclude="..\UniTask\Assets\Plugins\UniTask\Triggers\*.cs;
..\UniTask\Assets\Plugins\UniTask\Editor\*.cs;
..\UniTask\Assets\Plugins\UniTask\Internal\UnityEqualityComparer.cs;
..\UniTask\Assets\Plugins\UniTask\Internal\DiagnosticsExtensions.cs;
..\UniTask\Assets\Plugins\UniTask\Internal\PlayerLoopRunner.cs;
..\UniTask\Assets\Plugins\UniTask\CancellationTokenSourceExtensions.cs;
..\UniTask\Assets\Plugins\UniTask\EnumeratorAsyncExtensions.cs;
..\UniTask\Assets\Plugins\UniTask\PlayerLoopHelper.cs;
..\UniTask\Assets\Plugins\UniTask\UniTask.Delay.cs;
..\UniTask\Assets\Plugins\UniTask\UniTask.Run.cs;
..\UniTask\Assets\Plugins\UniTask\UniTask.Bridge.cs;
..\UniTask\Assets\Plugins\UniTask\UniTask.WaitUntil.cs;
..\UniTask\Assets\Plugins\UniTask\UnityAsyncExtensions.cs;
..\UniTask\Assets\Plugins\UniTask\UnityAsyncExtensions.uGUI.cs;
..\UniTask\Assets\Plugins\UniTask\UnityAsyncExtensions.MonoBehaviour.cs;
"/>
<Compile Include="..\UniTask\Assets\Plugins\UniTask\**\*.cs" Exclude="..\UniTask\Assets\Plugins\UniTask\Triggers\*.cs;&#xD;&#xA; ..\UniTask\Assets\Plugins\UniTask\Editor\*.cs;&#xD;&#xA; &#xD;&#xA; ..\UniTask\Assets\Plugins\UniTask\Internal\UnityEqualityComparer.cs;&#xD;&#xA; ..\UniTask\Assets\Plugins\UniTask\Internal\DiagnosticsExtensions.cs;&#xD;&#xA; ..\UniTask\Assets\Plugins\UniTask\Internal\PlayerLoopRunner.cs;&#xD;&#xA; &#xD;&#xA; ..\UniTask\Assets\Plugins\UniTask\CancellationTokenSourceExtensions.cs;&#xD;&#xA; ..\UniTask\Assets\Plugins\UniTask\EnumeratorAsyncExtensions.cs;&#xD;&#xA; ..\UniTask\Assets\Plugins\UniTask\PlayerLoopHelper.cs;&#xD;&#xA; ..\UniTask\Assets\Plugins\UniTask\UniTask.Delay.cs;&#xD;&#xA; ..\UniTask\Assets\Plugins\UniTask\UniTask.Run.cs;&#xD;&#xA; ..\UniTask\Assets\Plugins\UniTask\UniTask.Bridge.cs;&#xD;&#xA; ..\UniTask\Assets\Plugins\UniTask\UniTask.WaitUntil.cs;&#xD;&#xA; ..\UniTask\Assets\Plugins\UniTask\UnityAsyncExtensions.cs;&#xD;&#xA; ..\UniTask\Assets\Plugins\UniTask\UnityAsyncExtensions.uGUI.cs;&#xD;&#xA; ..\UniTask\Assets\Plugins\UniTask\UnityAsyncExtensions.MonoBehaviour.cs;&#xD;&#xA; " />
</ItemGroup>
</Project>

View File

@ -1,46 +1,227 @@
using Cysharp.Threading.Tasks;
using System.Linq;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Collections;
using System.Text;
using System.Text.RegularExpressions;
using System.Runtime.CompilerServices;
using Cysharp.Threading.Tasks.Linq;
namespace NetCoreSandbox
{
class Program
{
static string FlattenGenArgs(Type type)
{
if (type.IsGenericType)
{
var t = string.Join(", ", type.GetGenericArguments().Select(x => FlattenGenArgs(x)));
return Regex.Replace(type.Name, "`.+", "") + "<" + t + ">";
}
//x.ReturnType.GetGenericArguments()
else
{
return type.Name;
}
}
static async Task Main(string[] args)
{
Console.WriteLine("Foo");
var v = await outer().AsTask();
Console.WriteLine("Bar:" + v);
await UniTaskAsyncEnumerable.Range(1, 3).ForEachAsync(x =>
{
if (x == 2) throw new Exception();
Console.WriteLine(x);
});
}
static async UniTask<int> outer()
void Foo()
{
//await Task.WhenAll();
// AsyncEnumerable.t
var sb = new StringBuilder();
sb.AppendLine(@"using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
");
var chako = typeof(AsyncEnumerable).GetMethods()
.OrderBy(x => x.Name)
.Select(x =>
{
var ret = FlattenGenArgs(x.ReturnType);
var generics = string.Join(", ", x.GetGenericArguments().Select(x => x.Name));
if (x.GetParameters().Length == 0) return "";
var self = x.GetParameters().First();
if (x.GetCustomAttributes(typeof(ExtensionAttribute), true).Length == 0)
{
return "";
}
var arg1Type = FlattenGenArgs(x.GetParameters().First().ParameterType);
var others = string.Join(", ", x.GetParameters().Skip(1).Select(y => FlattenGenArgs(y.ParameterType) + " " + y.Name));
if (!string.IsNullOrEmpty(others))
{
others = ", " + others;
}
var template = $"public static {ret} {x.Name}<{generics}>(this {arg1Type} {self.Name}{others})";
return template.Replace("ValueTask", "UniTask").Replace("IAsyncEnumerable", "IUniTaskAsyncEnumerable").Replace("<>", "");
})
.Where(x => x != "")
.Select(x => x + "\r\n{\r\n throw new NotImplementedException();\r\n}")
.ToArray();
var huga = string.Join("\r\n\r\n", chako);
foreach (var item in typeof(AsyncEnumerable).GetMethods().Select(x => x.Name).Distinct())
{
if (item.EndsWith("AwaitAsync") || item.EndsWith("AwaitWithCancellationAsync") || item.EndsWith("WithCancellation"))
{
continue;
}
var item2 = item.Replace("Async", "");
item2 = item2.Replace("Await", "");
var format = @"
internal sealed class {0}
{{
}}
";
sb.Append(string.Format(format, item2));
}
sb.Append("}");
Console.WriteLine(sb.ToString());
//var foo = await Task.WhenAny(Array.Empty<Task<int>>());
await UniTask.WhenAny(new UniTask[0]);
return 10;
//var v = await DoAsync();
//return v;
}
static async UniTask<int> DoAsync()
public static async IAsyncEnumerable<int> AsyncGen()
{
var tcs = new UniTaskCompletionSource<int>();
tcs.TrySetResult(100);
var v = await tcs.Task;
return v;
await UniTask.SwitchToThreadPool();
yield return 10;
await UniTask.SwitchToThreadPool();
yield return 100;
}
}
class MyEnumerable : IEnumerable<int>
{
public IEnumerator<int> GetEnumerator()
{
return new MyEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
}
class MyEnumerator : IEnumerator<int>
{
public int Current => throw new NotImplementedException();
object IEnumerator.Current => throw new NotImplementedException();
public void Dispose()
{
Console.WriteLine("Called Dispose");
}
public bool MoveNext()
{
throw new NotImplementedException();
}
public void Reset()
{
throw new NotImplementedException();
}
}
public class MyClass<T>
{
public CustomAsyncEnumerator<T> GetAsyncEnumerator()
{
//IAsyncEnumerable
return new CustomAsyncEnumerator<T>();
}
}
public struct CustomAsyncEnumerator<T>
{
int count;
public T Current
{
get
{
return default;
}
}
public UniTask<bool> MoveNextAsync()
{
if (count++ == 3)
{
return UniTask.FromResult(false);
//return false;
}
return UniTask.FromResult(true);
}
public UniTask DisposeAsync()
{
return default;
}
}
}

View File

@ -6,6 +6,10 @@
<RootNamespace>NetCoreSandbox</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Interactive.Async" Version="4.1.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\UniTask.NetCore\UniTask.NetCore.csproj" />
</ItemGroup>

View File

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using Xunit;
namespace UniTask.NetCoreTests
@ -10,5 +11,9 @@ namespace UniTask.NetCoreTests
{
}
}
}

View File

@ -20,6 +20,12 @@ namespace Cysharp.Threading.Tasks.Internal
throw new ArgumentNullException(paramName);
}
[MethodImpl(MethodImplOptions.NoInlining)]
internal static Exception ArgumentOutOfRange(string paramName)
{
throw new ArgumentOutOfRangeException(paramName);
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowArgumentException<T>(string message)
{

View File

@ -32,7 +32,7 @@ public struct MyJob : IJob
public enum MyEnum
{
A,B,C
A, B, C
}
public class SandboxMain : MonoBehaviour
@ -85,6 +85,18 @@ public class SandboxMain : MonoBehaviour
job.inOut.Dispose();
}
async UniTaskVoid Update2()
{
async foreach (var _ in this.GetAsyncUpdateTrigger())
{
// do anything
}
}
void Start()
{
Application.SetStackTraceLogType(LogType.Error, StackTraceLogType.Full);

View File

@ -1,7 +1,7 @@
{
"dependencies": {
"com.unity.addressables": "1.8.3",
"com.unity.ads": "2.0.8",
"com.unity.ads": "3.4.4",
"com.unity.analytics": "3.3.5",
"com.unity.collab-proxy": "1.2.16",
"com.unity.ext.nunit": "1.0.0",

View File

@ -1,2 +1,2 @@
m_EditorVersion: 2019.3.9f1
m_EditorVersionWithRevision: 2019.3.9f1 (e6e740a1c473)
m_EditorVersion: 2019.3.11f1
m_EditorVersionWithRevision: 2019.3.11f1 (ceef2d848e70)