/
GeekNerd
/
ServerModelingProject
Обзор
Документация
Войти
/
GeekNerd
/
ServerModelingProject
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
Assets/Plugins/UniTask/Runtime/Linq/Queue.cs
103 строки
3 KB
Gorney-Alex
Init
30 май 2026, 19:05
30 май 2026, 19:05
3cdcc49
Код
Авторство
О чём код?
using System; using System.Threading; namespace Cysharp.Threading.Tasks.Linq { public static partial class UniTaskAsyncEnumerable { public static IUniTaskAsyncEnumerable<TSource> Queue<TSource>(this IUniTaskAsyncEnumerable<TSource> source) { return new QueueOperator<TSource>(source); } } internal sealed class QueueOperator<TSource> : IUniTaskAsyncEnumerable<TSource> { readonly IUniTaskAsyncEnumerable<TSource> source; public QueueOperator(IUniTaskAsyncEnumerable<TSource> source) { this.source = source; } public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default) { return new _Queue(source, cancellationToken); } sealed class _Queue : IUniTaskAsyncEnumerator<TSource> { readonly IUniTaskAsyncEnumerable<TSource> source; CancellationToken cancellationToken; Channel<TSource> channel; IUniTaskAsyncEnumerator<TSource> channelEnumerator; IUniTaskAsyncEnumerator<TSource> sourceEnumerator; bool channelClosed; public _Queue(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken) { this.source = source; this.cancellationToken = cancellationToken; } public TSource Current => channelEnumerator.Current; public UniTask<bool> MoveNextAsync() { cancellationToken.ThrowIfCancellationRequested(); if (sourceEnumerator == null) { sourceEnumerator = source.GetAsyncEnumerator(cancellationToken); channel = Channel.CreateSingleConsumerUnbounded<TSource>(); channelEnumerator = channel.Reader.ReadAllAsync().GetAsyncEnumerator(cancellationToken); ConsumeAll(this, sourceEnumerator, channel).Forget(); } return channelEnumerator.MoveNextAsync(); } static async UniTaskVoid ConsumeAll(_Queue self, IUniTaskAsyncEnumerator<TSource> enumerator, ChannelWriter<TSource> writer) { try { while (await enumerator.MoveNextAsync()) { writer.TryWrite(enumerator.Current); } writer.TryComplete(); } catch (Exception ex) { writer.TryComplete(ex); } finally { self.channelClosed = true; await enumerator.DisposeAsync(); } } public async UniTask DisposeAsync() { if (sourceEnumerator != null) { await sourceEnumerator.DisposeAsync(); } if (channelEnumerator != null) { await channelEnumerator.DisposeAsync(); } if (!channelClosed) { channelClosed = true; channel.Writer.TryComplete(new OperationCanceledException()); } } } } }