public static IAsyncObserver <TSource> ElementAtOrDefault <TSource>(IAsyncObserver <TSource> observer, int index) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } if (index < 0) { throw new ArgumentOutOfRangeException(nameof(index)); } return(Create <TSource>( async x => { if (index-- == 0) { await observer.OnNextAsync(x).ConfigureAwait(false); await observer.OnCompletedAsync().ConfigureAwait(false); } }, observer.OnErrorAsync, async() => { await observer.OnNextAsync(default).ConfigureAwait(false);
public static ValueTask <IAsyncDisposable> Timer(IAsyncObserver <long> observer, TimeSpan dueTime, IAsyncScheduler scheduler) { if (scheduler == null) { throw new ArgumentNullException(nameof(scheduler)); } return(scheduler.ScheduleAsync(async ct => { if (ct.IsCancellationRequested) { return; } await observer.OnNextAsync(0L).RendezVous(scheduler, ct); if (ct.IsCancellationRequested) { return; } await observer.OnCompletedAsync().RendezVous(scheduler, ct); }, dueTime)); }
public static IAsyncObserver <decimal> SumDecimal(IAsyncObserver <decimal> observer) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } var sum = 0m; return(Create <decimal>( x => { sum += x; return Task.CompletedTask; }, observer.OnErrorAsync, async() => { await observer.OnNextAsync(sum).ConfigureAwait(false); await observer.OnCompletedAsync().ConfigureAwait(false); } )); }
public static IAsyncObserver <double> SumDouble(IAsyncObserver <double> observer) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } var sum = 0.0; return(Create <double>( x => { sum += x; return default; }, observer.OnErrorAsync, async() => { await observer.OnNextAsync(sum).ConfigureAwait(false); await observer.OnCompletedAsync().ConfigureAwait(false); } )); }
public static Task <IAsyncDisposable> Generate <TState, TResult>(IAsyncObserver <TResult> observer, TState initialState, Func <TState, Task <bool> > condition, Func <TState, Task <TState> > iterate, Func <TState, Task <TResult> > resultSelector, Func <TState, Task <DateTimeOffset> > timeSelector, IAsyncScheduler scheduler) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } if (condition == null) { throw new ArgumentNullException(nameof(condition)); } if (iterate == null) { throw new ArgumentNullException(nameof(iterate)); } if (resultSelector == null) { throw new ArgumentNullException(nameof(resultSelector)); } if (timeSelector == null) { throw new ArgumentNullException(nameof(timeSelector)); } if (scheduler == null) { throw new ArgumentNullException(nameof(scheduler)); } return(scheduler.ScheduleAsync(async ct => { var first = true; var state = initialState; while (!ct.IsCancellationRequested) { var hasResult = false; var result = default(TResult); var nextDue = default(DateTimeOffset); try { if (first) { first = false; } else { state = await iterate(state).RendezVous(scheduler, ct); } hasResult = await condition(state).RendezVous(scheduler, ct); if (hasResult) { result = await resultSelector(state).RendezVous(scheduler, ct); nextDue = await timeSelector(state).RendezVous(scheduler, ct); } } catch (Exception ex) { await observer.OnErrorAsync(ex).RendezVous(scheduler, ct); return; } if (hasResult) { await observer.OnNextAsync(result).RendezVous(scheduler, ct); } else { break; } await scheduler.Delay(nextDue).RendezVous(scheduler, ct); } if (!ct.IsCancellationRequested) { await observer.OnCompletedAsync().RendezVous(scheduler, ct); } })); }
public Task OnCompletedAsync() { return(inner.OnCompletedAsync()); }
public static (IAsyncObserver <TSource>, IAsyncObserver <TSource>) Amb <TSource>(IAsyncObserver <TSource> observer, IAsyncDisposable first, IAsyncDisposable second) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } if (first == null) { throw new ArgumentNullException(nameof(first)); } if (second == null) { throw new ArgumentNullException(nameof(second)); } var gate = new AsyncLock(); var state = AmbState.None; return ( Create <TSource>( async x => { using (await gate.LockAsync().ConfigureAwait(false)) { if (state == AmbState.None) { state = AmbState.First; await second.DisposeAsync().ConfigureAwait(false); } if (state == AmbState.First) { await observer.OnNextAsync(x).ConfigureAwait(false); } } }, async ex => { using (await gate.LockAsync().ConfigureAwait(false)) { if (state == AmbState.None) { state = AmbState.First; await second.DisposeAsync().ConfigureAwait(false); } if (state == AmbState.First) { await observer.OnErrorAsync(ex).ConfigureAwait(false); } } }, async() => { using (await gate.LockAsync().ConfigureAwait(false)) { if (state == AmbState.None) { state = AmbState.First; await second.DisposeAsync().ConfigureAwait(false); } if (state == AmbState.First) { await observer.OnCompletedAsync().ConfigureAwait(false); } } } ), Create <TSource>( async x => { using (await gate.LockAsync().ConfigureAwait(false)) { if (state == AmbState.None) { state = AmbState.Second; await first.DisposeAsync().ConfigureAwait(false); } if (state == AmbState.Second) { await observer.OnNextAsync(x).ConfigureAwait(false); } } }, async ex => { using (await gate.LockAsync().ConfigureAwait(false)) { if (state == AmbState.None) { state = AmbState.Second; await first.DisposeAsync().ConfigureAwait(false); } if (state == AmbState.Second) { await observer.OnErrorAsync(ex).ConfigureAwait(false); } } }, async() => { using (await gate.LockAsync().ConfigureAwait(false)) { if (state == AmbState.None) { state = AmbState.Second; await first.DisposeAsync().ConfigureAwait(false); } if (state == AmbState.Second) { await observer.OnCompletedAsync().ConfigureAwait(false); } } } ) ); }
public static IAsyncObserver <TSource>[] Amb <TSource>(IAsyncObserver <TSource> observer, IAsyncDisposable[] subscriptions) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } if (subscriptions == null) { throw new ArgumentNullException(nameof(subscriptions)); } var gate = new AsyncLock(); var winner = default(int?); var count = subscriptions.Length; async Task ElectWinnerAsync(int index) { winner = index; var dispose = new List <Task>(count - 1); for (var i = 0; i < count; i++) { if (i != index) { dispose.Add(subscriptions[i].DisposeAsync().AsTask()); } } await Task.WhenAll(dispose).ConfigureAwait(false); } IAsyncObserver <TSource> CreateObserver(int index) => Create <TSource>( async x => { using (await gate.LockAsync().ConfigureAwait(false)) { if (winner == null) { await ElectWinnerAsync(index).ConfigureAwait(false); } if (winner == index) { await observer.OnNextAsync(x).ConfigureAwait(false); } } }, async ex => { using (await gate.LockAsync().ConfigureAwait(false)) { if (winner == null) { await ElectWinnerAsync(index).ConfigureAwait(false); } if (winner == index) { await observer.OnErrorAsync(ex).ConfigureAwait(false); } } }, async() => { using (await gate.LockAsync().ConfigureAwait(false)) { if (winner == null) { await ElectWinnerAsync(index).ConfigureAwait(false); } if (winner == index) { await observer.OnCompletedAsync().ConfigureAwait(false); } } } ); var res = new IAsyncObserver <TSource> [count]; for (var i = 0; i < count; i++) { res[i] = CreateObserver(i); } return(res); }
public void OnCompleted() => _observer.OnCompletedAsync().GetAwaiter().GetResult();
public async ValueTask Run() { await _observer.OnSubscribeAsync(this).ConfigureAwait(false); try { var done = false; while (true) { while (true) { if (IsCanceled) { return; } done = Volatile.Read(ref _done); if (_queue.TryDequeue(out var item)) { var t = _observer.OnNextAsync(item); try { await t.ConfigureAwait(false); } catch (Exception ex) { await _observer.OnErrorAsync(ex).ConfigureAwait(false); return; } } else { break; } } if (done) { break; } await ResumeHelper.Await(ref _tcs).ConfigureAwait(false); ResumeHelper.Clear(ref _tcs); } if (!IsCanceled) { if (_error == null) { await _observer.OnCompletedAsync().ConfigureAwait(false); } else { await _observer.OnErrorAsync(_error).ConfigureAwait(false); } } Dispose(); } finally { await _observer.OnFinallyAsync().ConfigureAwait(false); } }
public static (IAsyncObserver <TSource>, IAsyncObserver <TSource>) SequenceEqual <TSource>(IAsyncObserver <bool> observer, IEqualityComparer <TSource> comparer) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } if (comparer == null) { throw new ArgumentNullException(nameof(comparer)); } var gate = new AsyncLock(); var queueLeft = new Queue <TSource>(); var queueRight = new Queue <TSource>(); var doneLeft = false; var doneRight = false; return ( Create <TSource>( async x => { using (await gate.LockAsync().ConfigureAwait(false)) { if (queueRight.Count > 0) { var v = queueRight.Dequeue(); var equal = false; try { equal = comparer.Equals(x, v); } catch (Exception ex) { await observer.OnErrorAsync(ex).ConfigureAwait(false); return; } if (!equal) { await observer.OnNextAsync(false).ConfigureAwait(false); await observer.OnCompletedAsync().ConfigureAwait(false); } } else if (doneRight) { await observer.OnNextAsync(false).ConfigureAwait(false); await observer.OnCompletedAsync().ConfigureAwait(false); } else { queueLeft.Enqueue(x); } } }, async ex => { using (await gate.LockAsync().ConfigureAwait(false)) { await observer.OnErrorAsync(ex).ConfigureAwait(false); } }, async() => { using (await gate.LockAsync().ConfigureAwait(false)) { doneLeft = true; if (queueLeft.Count == 0) { if (queueRight.Count > 0) { await observer.OnNextAsync(false).ConfigureAwait(false); await observer.OnCompletedAsync().ConfigureAwait(false); } else if (doneRight) { await observer.OnNextAsync(true).ConfigureAwait(false); await observer.OnCompletedAsync().ConfigureAwait(false); } } } } ), Create <TSource>( async x => { using (await gate.LockAsync().ConfigureAwait(false)) { if (queueLeft.Count > 0) { var v = queueLeft.Dequeue(); var equal = false; try { equal = comparer.Equals(v, x); } catch (Exception ex) { await observer.OnErrorAsync(ex).ConfigureAwait(false); return; } if (!equal) { await observer.OnNextAsync(false).ConfigureAwait(false); await observer.OnCompletedAsync().ConfigureAwait(false); } } else if (doneLeft) { await observer.OnNextAsync(false).ConfigureAwait(false); await observer.OnCompletedAsync().ConfigureAwait(false); } else { queueRight.Enqueue(x); } } }, async ex => { using (await gate.LockAsync().ConfigureAwait(false)) { await observer.OnErrorAsync(ex).ConfigureAwait(false); } }, async() => { using (await gate.LockAsync().ConfigureAwait(false)) { doneRight = true; if (queueRight.Count == 0) { if (queueLeft.Count > 0) { await observer.OnNextAsync(false).ConfigureAwait(false); await observer.OnCompletedAsync().ConfigureAwait(false); } else if (doneLeft) { await observer.OnNextAsync(true).ConfigureAwait(false); await observer.OnCompletedAsync().ConfigureAwait(false); } } } } ) ); }
public Task CompleteStream() { return(observer == null ? TaskDone.Done : observer.OnCompletedAsync()); }
public static (IAsyncObserver <TFirst>, IAsyncObserver <TSecond>) WithLatestFrom <TFirst, TSecond, TResult>(IAsyncObserver <TResult> observer, Func <TFirst, TSecond, ValueTask <TResult> > resultSelector) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } if (resultSelector == null) { throw new ArgumentNullException(nameof(resultSelector)); } var gate = new AsyncLock(); async ValueTask OnErrorAsync(Exception ex) { using (await gate.LockAsync().ConfigureAwait(false)) { await observer.OnErrorAsync(ex).ConfigureAwait(false); } } var hasLatest = false; var latest = default(TSecond); return ( Create <TFirst>( async x => { using (await gate.LockAsync().ConfigureAwait(false)) { if (hasLatest) { var res = default(TResult); try { res = await resultSelector(x, latest).ConfigureAwait(false); } catch (Exception ex) { await observer.OnErrorAsync(ex).ConfigureAwait(false); return; } await observer.OnNextAsync(res).ConfigureAwait(false); } } }, OnErrorAsync, async() => { using (await gate.LockAsync().ConfigureAwait(false)) { await observer.OnCompletedAsync().ConfigureAwait(false); } } ), Create <TSecond>( async y => { using (await gate.LockAsync().ConfigureAwait(false)) { hasLatest = true; latest = y; } }, OnErrorAsync, () => default ) ); }
public static IAsyncObserver <TSource> Buffer <TSource>(IAsyncObserver <IList <TSource> > observer, int count, int skip) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } if (count <= 0) { throw new ArgumentNullException(nameof(count)); } if (skip <= 0) { throw new ArgumentNullException(nameof(skip)); } var queue = new Queue <IList <TSource> >(); var n = 0; void CreateBuffer() => queue.Enqueue(new List <TSource>()); CreateBuffer(); return(Create <TSource>( async x => { foreach (var buffer in queue) { buffer.Add(x); } var c = n - count + 1; if (c >= 0 && c % skip == 0) { var buffer = queue.Dequeue(); if (buffer.Count > 0) { await observer.OnNextAsync(buffer).ConfigureAwait(false); } } n++; if (n % skip == 0) { CreateBuffer(); } }, ex => { while (queue.Count > 0) { queue.Dequeue().Clear(); } return observer.OnErrorAsync(ex); }, async() => { while (queue.Count > 0) { var buffer = queue.Dequeue(); if (buffer.Count > 0) { await observer.OnNextAsync(buffer).ConfigureAwait(false); } } await observer.OnCompletedAsync().ConfigureAwait(false); } )); }
public Task OnCompletedAsync() => _observer.OnCompletedAsync();
public static IAsyncObserver <TSource> MinBy <TSource, TKey>(IAsyncObserver <IList <TSource> > observer, Func <TSource, Task <TKey> > keySelector, IComparer <TKey> comparer) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } if (keySelector == null) { throw new ArgumentNullException(nameof(keySelector)); } if (comparer == null) { throw new ArgumentNullException(nameof(comparer)); } var hasValue = false; var lastKey = default(TKey); var list = new List <TSource>(); return(Create <TSource>( async x => { var key = default(TKey); try { key = await keySelector(x).ConfigureAwait(false); } catch (Exception ex) { await observer.OnErrorAsync(ex).ConfigureAwait(false); return; } var comparison = 0; if (!hasValue) { hasValue = true; lastKey = key; } else { try { comparison = comparer.Compare(key, lastKey); } catch (Exception ex) { await observer.OnErrorAsync(ex).ConfigureAwait(false); return; } } if (comparison < 0) { lastKey = key; list.Clear(); } if (comparison <= 0) { list.Add(x); } }, observer.OnErrorAsync, async() => { await observer.OnNextAsync(list).ConfigureAwait(false); await observer.OnCompletedAsync().ConfigureAwait(false); } )); }
public static (IAsyncObserver <TSource>, IAsyncObserver <TSample>) Sample <TSource, TSample>(IAsyncObserver <TSource> observer) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } var gate = new AsyncLock(); var hasValue = false; var value = default(TSource); var atEnd = false; async ValueTask OnSampleAsync() { using (await gate.LockAsync().ConfigureAwait(false)) { if (hasValue) { hasValue = false; await observer.OnNextAsync(value).ConfigureAwait(false); } if (atEnd) { await observer.OnCompletedAsync().ConfigureAwait(false); } } } return ( Create <TSource>( async x => { using (await gate.LockAsync().ConfigureAwait(false)) { hasValue = true; value = x; } }, async ex => { using (await gate.LockAsync().ConfigureAwait(false)) { await observer.OnErrorAsync(ex).ConfigureAwait(false); } }, async() => { using (await gate.LockAsync().ConfigureAwait(false)) { atEnd = true; } } ), Create <TSample>( _ => OnSampleAsync(), async ex => { using (await gate.LockAsync().ConfigureAwait(false)) { await observer.OnErrorAsync(ex).ConfigureAwait(false); } }, OnSampleAsync ) ); }
public static Task <IAsyncDisposable> AcceptAsync(this Task task, IAsyncObserver <Unit> observer, IAsyncScheduler scheduler) { if (task == null) { throw new ArgumentNullException(nameof(task)); } if (observer == null) { throw new ArgumentNullException(nameof(observer)); } if (scheduler == null) { throw new ArgumentNullException(nameof(scheduler)); } Task <IAsyncDisposable> CompleteAsync() { return(scheduler.ScheduleAsync(async ct => { if (ct.IsCancellationRequested) { return; } switch (task.Status) { case TaskStatus.RanToCompletion: await observer.OnNextAsync(Unit.Default).RendezVous(scheduler, ct); await observer.OnCompletedAsync().RendezVous(scheduler, ct); break; case TaskStatus.Faulted: await observer.OnErrorAsync(task.Exception.InnerException).RendezVous(scheduler, ct); break; case TaskStatus.Canceled: await observer.OnErrorAsync(new TaskCanceledException(task)).RendezVous(scheduler, ct); break; } })); } Task <IAsyncDisposable> CoreAsync() { if (task.IsCompleted) { return(CompleteAsync()); } else { var tco = TaskContinuationOptions.None; if (scheduler == ImmediateAsyncScheduler.Instance) { tco = TaskContinuationOptions.ExecuteSynchronously; } var subject = new SequentialAsyncAsyncSubject <Unit>(); task.ContinueWith(t => CompleteAsync(), tco); return(subject.SubscribeAsync(observer)); } } return(CoreAsync()); }
public static IAsyncObserver <TSource>[] Zip <TSource>(IAsyncObserver <IList <TSource> > observer, int count) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } if (count < 0) { throw new ArgumentOutOfRangeException(nameof(count)); } var gate = new AsyncLock(); var queues = new Queue <TSource> [count]; var isDone = new bool[count]; var res = new IAsyncObserver <TSource> [count]; IAsyncObserver <TSource> CreateObserver(int index) => Create <TSource>( async x => { using (await gate.LockAsync().ConfigureAwait(false)) { queues[index].Enqueue(x); if (queues.All(queue => queue.Count > 0)) { var list = new TSource[count]; for (var i = 0; i < count; i++) { list[i] = queues[i].Dequeue(); } await observer.OnNextAsync(list).ConfigureAwait(false); } else { var allDone = true; for (var i = 0; i < count; i++) { if (i != index && !isDone[i]) { allDone = false; break; } } if (allDone) { await observer.OnCompletedAsync().ConfigureAwait(false); } } } }, async ex => { using (await gate.LockAsync().ConfigureAwait(false)) { await observer.OnErrorAsync(ex).ConfigureAwait(false); } }, async() => { using (await gate.LockAsync().ConfigureAwait(false)) { isDone[index] = true; var allDone = true; for (var i = 0; i < count; i++) { if (!isDone[i]) { allDone = false; break; } } if (allDone) { await observer.OnCompletedAsync().ConfigureAwait(false); } } } ); for (var i = 0; i < count; i++) { queues[i] = new Queue <TSource>(); res[i] = CreateObserver(i); } return(res); }
protected async Task RunAsync(CancellationToken token) { while (!token.IsCancellationRequested) { var values = default(T[]); var error = default(Exception); var done = false; using (await RendezVous(_lock.LockAsync())) { if (_queue.Count > 0) { values = _queue.ToArray(); _queue.Clear(); } if (_done) { done = _done; error = _error; } if (values == null && !done) { _busy = false; break; } } try { if (values != null) { foreach (var value in values) { await RendezVous(_observer.OnNextAsync(value)); } } if (done) { if (error != null) { await RendezVous(_observer.OnErrorAsync(error)); } else { await RendezVous(_observer.OnCompletedAsync()); } break; } } catch { using (await RendezVous(_lock.LockAsync())) { _hasFaulted = true; _queue.Clear(); } throw; } } }
public async Task OnCompletedAsync() { await _observer.OnCompletedAsync(); }