public static IAsyncObservable <TSource> ToAsyncObservable <TSource>(this IObservable <TSource> source, IAsyncScheduler subscribeScheduler, IAsyncScheduler disposeScheduler) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (subscribeScheduler == null) { throw new ArgumentNullException(nameof(subscribeScheduler)); } if (disposeScheduler == null) { throw new ArgumentNullException(nameof(disposeScheduler)); } return(Create <TSource>(async observer => { var d = new CompositeAsyncDisposable(); var subscribeTask = await subscribeScheduler.ScheduleAsync(async ct => { ct.ThrowIfCancellationRequested(); var disposable = source.Subscribe(AsyncObserver.ToObserver(observer)); var disposeTask = AsyncDisposable.Create(() => disposeScheduler.ExecuteAsync(_ => { disposable.Dispose(); return default; })); await d.AddAsync(disposeTask).RendezVous(subscribeScheduler); }).ConfigureAwait(false); await d.AddAsync(subscribeTask).ConfigureAwait(false); return d; })); }
public static IAsyncObservable <TSource> TakeUntil <TSource>(this IAsyncObservable <TSource> source, DateTimeOffset endTime, IAsyncScheduler scheduler) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (scheduler == null) { throw new ArgumentNullException(nameof(scheduler)); } // REVIEW: May be easier to just use TakeUntil with a Timer parameter. Do we want TakeUntil on the observer? return(Create <TSource>(async observer => { var(sourceObserver, timer) = await AsyncObserver.TakeUntil(observer, endTime, scheduler).ConfigureAwait(false); var subscription = await source.SubscribeSafeAsync(sourceObserver).ConfigureAwait(false); return StableCompositeAsyncDisposable.Create(subscription, timer); })); }
public static IAsyncObservable <TSource> SkipLast <TSource>(this IAsyncObservable <TSource> source, TimeSpan duration, IClock clock) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (duration < TimeSpan.Zero) { throw new ArgumentOutOfRangeException(nameof(duration)); } if (clock == null) { throw new ArgumentNullException(nameof(clock)); } if (duration == TimeSpan.Zero) { return(source); } return(Create <TSource>(observer => source.SubscribeSafeAsync(AsyncObserver.SkipLast(observer, duration, clock)))); }
public static IAsyncObservable <TResult> Join <TLeft, TRight, TLeftDuration, TRightDuration, TResult>(this IAsyncObservable <TLeft> left, IAsyncObservable <TRight> right, Func <TLeft, IAsyncObservable <TLeftDuration> > leftDurationSelector, Func <TRight, IAsyncObservable <TRightDuration> > rightDurationSelector, Func <TLeft, TRight, TResult> resultSelector) { if (left == null) { throw new ArgumentNullException(nameof(left)); } if (right == null) { throw new ArgumentNullException(nameof(right)); } if (leftDurationSelector == null) { throw new ArgumentNullException(nameof(leftDurationSelector)); } if (rightDurationSelector == null) { throw new ArgumentNullException(nameof(rightDurationSelector)); } if (resultSelector == null) { throw new ArgumentNullException(nameof(resultSelector)); } return(Create <TResult>(async observer => { var subscriptions = new CompositeAsyncDisposable(); var(leftObserver, rightObserver, disposable) = AsyncObserver.Join(observer, subscriptions, leftDurationSelector, rightDurationSelector, resultSelector); var leftSubscription = await left.SubscribeSafeAsync(leftObserver).ConfigureAwait(false); await subscriptions.AddAsync(leftSubscription).ConfigureAwait(false); var rightSubscription = await right.SubscribeSafeAsync(rightObserver).ConfigureAwait(false); await subscriptions.AddAsync(rightSubscription).ConfigureAwait(false); return disposable; })); }
public static IAsyncObservable <TSource> Timeout <TSource>(this IAsyncObservable <TSource> source, TimeSpan dueTime) { if (source == null) { throw new ArgumentNullException(nameof(source)); } return(CreateAsyncObservable <TSource> .From( source, dueTime, static async (source, dueTime, observer) => { var sourceSubscription = new SingleAssignmentAsyncDisposable(); var(sink, disposable) = await AsyncObserver.Timeout(observer, sourceSubscription, dueTime).ConfigureAwait(false); var sourceSubscriptionInner = await source.SubscribeSafeAsync(sink).ConfigureAwait(false); await sourceSubscription.AssignAsync(sourceSubscriptionInner).ConfigureAwait(false); return disposable; })); }
public static IAsyncObservable <TSource> Sample <TSource>(this IAsyncObservable <TSource> source, TimeSpan interval, IAsyncScheduler scheduler) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (scheduler == null) { throw new ArgumentNullException(nameof(scheduler)); } return(CreateAsyncObservable <TSource> .From( source, (scheduler, interval), static async (source, state, observer) => { var(sourceSink, sampler) = await AsyncObserver.Sample(observer, state.interval, state.scheduler).ConfigureAwait(false); var sourceSubscription = await source.SubscribeSafeAsync(sourceSink).ConfigureAwait(false); return StableCompositeAsyncDisposable.Create(sourceSubscription, sampler); })); }
public static IAsyncObservable <TResult> SelectMany <TSource, TResult>(this IAsyncObservable <TSource> source, Func <TSource, ValueTask <IAsyncObservable <TResult> > > selector) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (selector == null) { throw new ArgumentNullException(nameof(selector)); } return(CreateAsyncObservable <TResult> .From( source, selector, static async (source, selector, observer) => { var(sink, inner) = AsyncObserver.SelectMany(observer, selector); var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false); return StableCompositeAsyncDisposable.Create(subscription, inner); })); }
public static IAsyncObservable <TSource> Delay <TSource>(this IAsyncObservable <TSource> source, TimeSpan dueTime, IAsyncScheduler scheduler) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (scheduler == null) { throw new ArgumentNullException(nameof(scheduler)); } return(Create( source, (dueTime, scheduler), static async(source, state, observer) => { var(sink, drain) = await AsyncObserver.Delay(observer, state.dueTime, state.scheduler).ConfigureAwait(false); var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false); return StableCompositeAsyncDisposable.Create(subscription, drain); })); }
public static IAsyncObservable <TSource> Catch <TSource>(this IAsyncObservable <TSource> first, IAsyncObservable <TSource> second) { if (first == null) { throw new ArgumentNullException(nameof(first)); } if (second == null) { throw new ArgumentNullException(nameof(second)); } return(Create( first, second, static async(first, second, observer) => { var(sink, inner) = AsyncObserver.Catch(observer, second); var subscription = await first.SubscribeSafeAsync(sink).ConfigureAwait(false); return StableCompositeAsyncDisposable.Create(subscription, inner); })); }
public static IAsyncObservable <IList <TSource> > Buffer <TSource>(this IAsyncObservable <TSource> source, TimeSpan timeSpan, TimeSpan timeShift) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (timeSpan < TimeSpan.Zero) { throw new ArgumentNullException(nameof(timeSpan)); } if (timeShift < TimeSpan.Zero) { throw new ArgumentNullException(nameof(timeShift)); } return(Create <IList <TSource> >(async observer => { var(sink, timer) = await AsyncObserver.Buffer(observer, timeSpan, timeShift).ConfigureAwait(false); var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false); return StableCompositeAsyncDisposable.Create(subscription, timer); })); }
public static IAsyncObservable <TResult> SelectMany <TSource, TCollection, TResult>(this IAsyncObservable <TSource> source, Func <TSource, IAsyncObservable <TCollection> > collectionSelector, Func <TSource, TCollection, TResult> resultSelector) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (collectionSelector == null) { throw new ArgumentNullException(nameof(collectionSelector)); } if (resultSelector == null) { throw new ArgumentNullException(nameof(resultSelector)); } return(Create <TResult>(async observer => { var(sink, inner) = AsyncObserver.SelectMany(observer, collectionSelector, resultSelector); var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false); return StableCompositeAsyncDisposable.Create(subscription, inner); })); }
public static IAsyncObservable <ILookup <TKey, TValue> > ToLookup <TSource, TKey, TValue>(this IAsyncObservable <TSource> source, Func <TSource, ValueTask <TKey> > keySelector, Func <TSource, ValueTask <TValue> > valueSelector, IEqualityComparer <TKey> comparer) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (keySelector == null) { throw new ArgumentNullException(nameof(keySelector)); } if (valueSelector == null) { throw new ArgumentNullException(nameof(valueSelector)); } if (comparer == null) { throw new ArgumentNullException(nameof(comparer)); } return(CreateAsyncObservable <ILookup <TKey, TValue> > .From( source, (keySelector, valueSelector, comparer), static (source, state, observer) => source.SubscribeSafeAsync(AsyncObserver.ToLookup(observer, state.keySelector, state.valueSelector, state.comparer)))); }
public static IAsyncObservable <TSource> TakeLast <TSource>(this IAsyncObservable <TSource> source, TimeSpan duration, IClock clock, IAsyncScheduler scheduler) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (duration < TimeSpan.Zero) { throw new ArgumentOutOfRangeException(nameof(duration)); } if (clock == null) { throw new ArgumentNullException(nameof(clock)); } if (scheduler == null) { throw new ArgumentNullException(nameof(scheduler)); } if (duration == TimeSpan.Zero) { return(Empty <TSource>()); } return(CreateAsyncObservable <TSource> .From( source, (duration, clock, scheduler), static async (source, state, observer) => { var(sink, drain) = AsyncObserver.TakeLast(observer, state.duration, state.clock, state.scheduler); var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false); return StableCompositeAsyncDisposable.Create(subscription, drain); })); }
public static IAsyncObservable <TSource> Catch <TSource, TException>(this IAsyncObservable <TSource> source, Func <TException, ValueTask <IAsyncObservable <TSource> > > handler) where TException : Exception { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (handler == null) { throw new ArgumentNullException(nameof(handler)); } return(Create( source, handler, static async(source, handler, observer) => { var(sink, inner) = AsyncObserver.Catch(observer, handler); var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false); return StableCompositeAsyncDisposable.Create(subscription, inner); })); }
public static IAsyncObservable <TSource> Sample <TSource, TSample>(this IAsyncObservable <TSource> source, IAsyncObservable <TSample> sampler) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (sampler == null) { throw new ArgumentNullException(nameof(sampler)); } return(CreateAsyncObservable <TSource> .From( source, sampler, static async (source, sampler, observer) => { var(sourceSink, samplerSink) = AsyncObserver.Sample <TSource, TSample>(observer); var sourceSubscription = await source.SubscribeSafeAsync(sourceSink).ConfigureAwait(false); var samplerSubscription = await sampler.SubscribeSafeAsync(samplerSink).ConfigureAwait(false); return StableCompositeAsyncDisposable.Create(sourceSubscription, samplerSubscription); })); }
public static IAsyncObservable <TSource> Do <TSource>(this IAsyncObservable <TSource> source, Action <TSource> onNext, Action <Exception> onError, Action onCompleted) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (onNext == null) { throw new ArgumentNullException(nameof(onNext)); } if (onError == null) { throw new ArgumentNullException(nameof(onError)); } if (onCompleted == null) { throw new ArgumentNullException(nameof(onCompleted)); } return(Create( source, (onNext, onError, onCompleted), (source, state, target) => source.SubscribeSafeAsync(AsyncObserver.Do(target, state.onNext, state.onError, state.onCompleted)))); }
public static IAsyncObservable <TSource> Prepend <TSource>(this IAsyncObservable <TSource> source, IEnumerable <TSource> values) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (values == null) { throw new ArgumentNullException(nameof(values)); } return(CreateAsyncObservable <TSource> .From( source, values, static async (source, values, observer) => await source.SubscribeSafeAsync(await AsyncObserver.Prepend(observer, values).ConfigureAwait(false)).ConfigureAwait(false))); }
public static IAsyncObservable <TSource> DoWhile <TSource>(IAsyncObservable <TSource> source, Func <Task <bool> > condition) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (condition == null) { throw new ArgumentNullException(nameof(condition)); } return(Create <TSource>(async observer => { var subscription = new SerialAsyncDisposable(); var o = default(IAsyncObserver <TSource>); o = AsyncObserver.CreateUnsafe <TSource>( observer.OnNextAsync, observer.OnErrorAsync, MoveNext ); async Task Subscribe() { var sad = new SingleAssignmentAsyncDisposable(); await subscription.AssignAsync(sad).ConfigureAwait(false); var d = await source.SubscribeSafeAsync(o).ConfigureAwait(false); await sad.AssignAsync(d).ConfigureAwait(false); } async Task MoveNext() { var b = default(bool); try { b = await condition().ConfigureAwait(false); } catch (Exception ex) { await observer.OnErrorAsync(ex).ConfigureAwait(false); return; } if (b) { await Subscribe().ConfigureAwait(false); } else { await observer.OnCompletedAsync().ConfigureAwait(false); } } await Subscribe().ConfigureAwait(false); return subscription; })); }
public static IAsyncObservable <IGroupedAsyncObservable <TKey, TSource> > GroupByUntil <TSource, TKey, TDuration>(this IAsyncObservable <TSource> source, Func <TSource, TKey> keySelector, Func <IGroupedAsyncObservable <TKey, TSource>, IAsyncObservable <TDuration> > durationSelector, int capacity, IEqualityComparer <TKey> comparer) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (keySelector == null) { throw new ArgumentNullException(nameof(keySelector)); } if (durationSelector == null) { throw new ArgumentNullException(nameof(durationSelector)); } if (capacity < 0) { throw new ArgumentOutOfRangeException(nameof(capacity)); } if (comparer == null) { throw new ArgumentNullException(nameof(comparer)); } return(Create <IGroupedAsyncObservable <TKey, TSource> >(observer => GroupByUntilCore <TSource, TKey, TSource, TDuration>(source, observer, (o, d) => AsyncObserver.GroupByUntil(o, d, keySelector, durationSelector, capacity, comparer)))); }
public static IAsyncObservable <IGroupedAsyncObservable <TKey, TElement> > GroupByUntil <TSource, TKey, TElement, TDuration>(this IAsyncObservable <TSource> source, Func <TSource, ValueTask <TKey> > keySelector, Func <TSource, ValueTask <TElement> > elementSelector, Func <IGroupedAsyncObservable <TKey, TElement>, IAsyncObservable <TDuration> > durationSelector, IEqualityComparer <TKey> comparer) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (keySelector == null) { throw new ArgumentNullException(nameof(keySelector)); } if (elementSelector == null) { throw new ArgumentNullException(nameof(elementSelector)); } if (durationSelector == null) { throw new ArgumentNullException(nameof(durationSelector)); } if (comparer == null) { throw new ArgumentNullException(nameof(comparer)); } return(Create <IGroupedAsyncObservable <TKey, TElement> >(observer => GroupByUntilCore <TSource, TKey, TElement, TDuration>(source, observer, (o, d) => AsyncObserver.GroupByUntil(o, d, keySelector, elementSelector, durationSelector, comparer)))); }
public static IAsyncObservable <IGroupedAsyncObservable <TKey, TSource> > GroupByUntil <TSource, TKey, TDuration>(this IAsyncObservable <TSource> source, Func <TSource, TKey> keySelector, Func <IGroupedAsyncObservable <TKey, TSource>, IAsyncObservable <TDuration> > durationSelector) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (keySelector == null) { throw new ArgumentNullException(nameof(keySelector)); } if (durationSelector == null) { throw new ArgumentNullException(nameof(durationSelector)); } return(Create <IGroupedAsyncObservable <TKey, TSource> >(observer => GroupByUntilCore <TSource, TKey, TSource, TDuration>(source, observer, (o, d) => AsyncObserver.GroupByUntil(o, d, keySelector, durationSelector)))); }
public static IAsyncObservable <TimeInterval <TSource> > TimeInterval <TSource>(this IAsyncObservable <TSource> source, IClock clock) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (clock == null) { throw new ArgumentNullException(nameof(clock)); } return(Create <TimeInterval <TSource> >(observer => source.SubscribeSafeAsync(AsyncObserver.TimeInterval(observer, clock)))); }
public static IAsyncObservable <IAsyncObservable <TSource> > Window <TSource>(this IAsyncObservable <TSource> source, TimeSpan timeSpan, TimeSpan timeShift, IAsyncScheduler scheduler) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (timeSpan < TimeSpan.Zero) { throw new ArgumentOutOfRangeException(nameof(timeSpan)); } if (timeShift < TimeSpan.Zero) { throw new ArgumentOutOfRangeException(nameof(timeShift)); } if (scheduler == null) { throw new ArgumentNullException(nameof(scheduler)); } return(Create <IAsyncObservable <TSource> >(observer => WindowAsyncCore(source, observer, (o, d) => AsyncObserver.Window(o, d, timeSpan, timeShift, scheduler)))); }
public static IAsyncObservable <TSource> Repeat <TSource>(TSource value) { return(Create <TSource>(observer => AsyncObserver.Repeat(observer, value))); }
private static async Task ForEachAsyncCore <TSource>(IAsyncObservable <TSource> source, Func <TSource, int, Task> onNext, CancellationToken token) { token.ThrowIfCancellationRequested(); var tcs = new TaskCompletionSource <object>(); var subscription = new SingleAssignmentAsyncDisposable(); using (token.Register(() => { tcs.TrySetCanceled(token); subscription.DisposeAsync().AsTask().ContinueWith(t => { if (t.Exception != null) { // TODO: Trace? } }); })) { var i = 0; var o = AsyncObserver.Create <TSource>( async x => { try { await onNext(x, checked (i++)).ConfigureAwait(false); } catch (Exception ex) { try { tcs.TrySetException(ex); } finally { await subscription.DisposeAsync().ConfigureAwait(false); } } }, async ex => { try { tcs.TrySetException(ex); } finally { await subscription.DisposeAsync().ConfigureAwait(false); } }, async() => { try { tcs.TrySetResult(null); } finally { await subscription.DisposeAsync().ConfigureAwait(false); } } ); // // NB: If any of the lines below throw, the result will go into the Task returned from the async method. // There's also no need to use SubscribeSafeAsync here; the exception will propagate just fine. // var d = await source.SubscribeAsync(o).ConfigureAwait(false); await subscription.AssignAsync(d).ConfigureAwait(false); } await tcs.Task.ConfigureAwait(false); }
public static IAsyncObservable <ILookup <TKey, TValue> > ToLookup <TSource, TKey, TValue>(this IAsyncObservable <TSource> source, Func <TSource, Task <TKey> > keySelector, Func <TSource, Task <TValue> > valueSelector) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (keySelector == null) { throw new ArgumentNullException(nameof(keySelector)); } if (valueSelector == null) { throw new ArgumentNullException(nameof(valueSelector)); } return(Create <ILookup <TKey, TValue> >(observer => source.SubscribeSafeAsync(AsyncObserver.ToLookup(observer, keySelector, valueSelector)))); }
public static IAsyncObservable <TSource> Empty <TSource>() { return(Create <TSource>(observer => AsyncObserver.Empty(observer))); }
public static IAsyncObservable <long> Timer(TimeSpan dueTime) { return(Create <long>(observer => AsyncObserver.Timer(observer, dueTime))); }
public static IAsyncObservable <long> Timer(DateTimeOffset dueTime) { return(Create <long>(observer => AsyncObserver.Timer(observer, dueTime))); }
public static IAsyncObservable <IAsyncObservable <TSource> > Window <TSource>(this IAsyncObservable <TSource> source, int count, int skip) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (count <= 0) { throw new ArgumentOutOfRangeException(nameof(count)); } if (skip <= 0) { throw new ArgumentOutOfRangeException(nameof(skip)); } return(Create <IAsyncObservable <TSource> >(observer => WindowCore(source, observer, (o, d) => AsyncObserver.Window(o, d, count, skip)))); }