public static ISequence <ISequence <T> > Window <T>(this ISequence <T> source, int windowSize, int queueLimit = 1) { if (queueLimit < 1) { throw new ArgumentOutOfRangeException("queueLimit must be greater that one."); } return(Create <ISequence <T> >(context => { Task <bool> lastCopyToResult = null; var i = source.Start(context); var subscription = new RefCountDisposable(i); return Iterator.Create <ISequence <T> >(async(r, c) => { if (lastCopyToResult != null && await lastCopyToResult.ConfigureAwait(false) == false) { return false; } if (!await i.MoveNext(c).ConfigureAwait(false)) { return false; } var queue = new AsyncQueue <T>(queueLimit); await queue.OnNext(i.Current, c).ConfigureAwait(false); r.Value = Create(context2 => new AnonymousIterator <T>(queue.MoveNext, () => queue.Current, queue.Dispose, Enumerable.Empty <Task>, context2)); var keepAlive = subscription.GetDisposable(); lastCopyToResult = CopyToQueue(i, queue, windowSize - 1, CancellationToken.None, true).Finally(keepAlive.Dispose); return true; }, context, subscription); })); }
private static async Task <bool> CopyToQueue <T>(this IIterator <T> source, AsyncQueue <T> destination, int count, CancellationToken cancel, bool complete = false) { try { for (; count > 0; --count) { if (!await source.MoveNext(cancel).ConfigureAwait(false)) { if (complete) { destination.OnCompleted(); } return(false); } await destination.OnNext(source.Current, cancel).ConfigureAwait(false); } if (complete) { destination.OnCompleted(); } } catch (Exception e) { destination.OnError(e); throw; } return(true); }
async Task Read(IIterator <T> iterator, CancellationToken cancel) { try { while (await iterator.MoveNext(cancel).ConfigureAwait(false)) { await queue.OnNext(iterator.Current, cancel).ConfigureAwait(false); } } catch (Exception e) { queue.OnError(e); iterator.Cancel(); } }
async Task Read() { try { while (await SourceIterator.MoveNext(CancellationToken.None).ConfigureAwait(false)) { try { await Queue.OnNext(SourceIterator.Current, CancellationToken.None).ConfigureAwait(false); } catch (OperationCanceledException) { } } } catch { if (SourceIterator != null) { SourceIterator.Cancel(); } throw; } }