Example #1
0
 public DontForgetAboutSingleReponsibilityPrinciple(
     Disposable dispo,
     Foo foo,
     Bar bar,
     IFirst0 first0,
     IFirst1 first1,
     IFirst2 first2,
     ISecond0 second0,
     ISecond1 second1,
     ISecond2 second2,
     IThird0 third0,
     IThird1 third1)
 {
 }
        private static IAsyncEnumerable <TSource> Concat_ <TSource>(this IEnumerable <IAsyncEnumerable <TSource> > sources)
        {
            return(Create(() =>
            {
                var se = sources.GetEnumerator();
                var e = default(IAsyncEnumerator <TSource>);

                var cts = new CancellationTokenDisposable();
                var a = new AssignableDisposable();
                var d = Disposable.Create(cts, se, a);

                var f = default(Action <TaskCompletionSource <bool>, CancellationToken>);
                f = (tcs, ct) =>
                {
                    if (e == null)
                    {
                        var b = false;
                        try
                        {
                            b = se.MoveNext();
                            if (b)
                            {
                                e = se.Current.GetEnumerator();
                            }
                        }
                        catch (Exception ex)
                        {
                            tcs.TrySetException(ex);
                            return;
                        }

                        if (!b)
                        {
                            tcs.TrySetResult(false);
                            return;
                        }

                        a.Disposable = e;
                    }

                    e.MoveNext(ct).Then(t =>
                    {
                        t.Handle(tcs, res =>
                        {
                            if (res)
                            {
                                tcs.TrySetResult(true);
                            }
                            else
                            {
                                e.Dispose();
                                e = null;

                                f(tcs, ct);
                            }
                        });
                    });
                };

                return Create(
                    (ct, tcs) =>
                {
                    f(tcs, cts.Token);
                    return tcs.Task.UsingEnumerator(a);
                },
                    () => e.Current,
                    d.Dispose
                    );
            }));
        }
        public static IAsyncEnumerable <TResult> GroupJoin <TOuter, TInner, TKey, TResult>(this IAsyncEnumerable <TOuter> outer, IAsyncEnumerable <TInner> inner, Func <TOuter, TKey> outerKeySelector, Func <TInner, TKey> innerKeySelector, Func <TOuter, IAsyncEnumerable <TInner>, TResult> resultSelector, IEqualityComparer <TKey> comparer)
        {
            if (outer == null)
            {
                throw new ArgumentNullException("outer");
            }
            if (inner == null)
            {
                throw new ArgumentNullException("inner");
            }
            if (outerKeySelector == null)
            {
                throw new ArgumentNullException("outerKeySelector");
            }
            if (innerKeySelector == null)
            {
                throw new ArgumentNullException("innerKeySelector");
            }
            if (resultSelector == null)
            {
                throw new ArgumentNullException("resultSelector");
            }
            if (comparer == null)
            {
                throw new ArgumentNullException("comparer");
            }

            return(Create(() =>
            {
                var innerMap = default(Task <ILookup <TKey, TInner> >);
                var getInnerMap = new Func <CancellationToken, Task <ILookup <TKey, TInner> > >(ct =>
                {
                    if (innerMap == null)
                    {
                        innerMap = inner.ToLookup(innerKeySelector, comparer, ct);
                    }

                    return innerMap;
                });

                var outerE = outer.GetEnumerator();
                var current = default(TResult);

                var cts = new CancellationTokenDisposable();
                var d = Disposable.Create(cts, outerE);

                var f = default(Action <TaskCompletionSource <bool>, CancellationToken>);
                f = (tcs, ct) =>
                {
                    getInnerMap(ct).Then(ti =>
                    {
                        ti.Handle(tcs, map =>
                        {
                            outerE.MoveNext(ct).Then(to =>
                            {
                                to.Handle(tcs, res =>
                                {
                                    if (res)
                                    {
                                        var element = outerE.Current;
                                        var key = default(TKey);

                                        try
                                        {
                                            key = outerKeySelector(element);
                                        }
                                        catch (Exception ex)
                                        {
                                            tcs.TrySetException(ex);
                                            return;
                                        }

                                        var innerE = default(IAsyncEnumerable <TInner>);
                                        if (!map.Contains(key))
                                        {
                                            innerE = AsyncEnumerable.Empty <TInner>();
                                        }
                                        else
                                        {
                                            innerE = map[key].ToAsyncEnumerable();
                                        }

                                        try
                                        {
                                            current = resultSelector(element, innerE);
                                        }
                                        catch (Exception ex)
                                        {
                                            tcs.TrySetException(ex);
                                            return;
                                        }

                                        tcs.TrySetResult(true);
                                    }
                                    else
                                    {
                                        tcs.TrySetResult(false);
                                    }
                                });
                            });
                        });
                    });
                };

                return Create(
                    (ct, tcs) =>
                {
                    f(tcs, cts.Token);
                    return tcs.Task.UsingEnumerator(outerE);
                },
                    () => current,
                    d.Dispose
                    );
            }));
        }
        public static IAsyncEnumerable <TResult> Join <TOuter, TInner, TKey, TResult>(this IAsyncEnumerable <TOuter> outer, IAsyncEnumerable <TInner> inner, Func <TOuter, TKey> outerKeySelector, Func <TInner, TKey> innerKeySelector, Func <TOuter, TInner, TResult> resultSelector, IEqualityComparer <TKey> comparer)
        {
            if (outer == null)
            {
                throw new ArgumentNullException("outer");
            }
            if (inner == null)
            {
                throw new ArgumentNullException("inner");
            }
            if (outerKeySelector == null)
            {
                throw new ArgumentNullException("outerKeySelector");
            }
            if (innerKeySelector == null)
            {
                throw new ArgumentNullException("innerKeySelector");
            }
            if (resultSelector == null)
            {
                throw new ArgumentNullException("resultSelector");
            }
            if (comparer == null)
            {
                throw new ArgumentNullException("comparer");
            }

            return(Create(() =>
            {
                var oe = outer.GetEnumerator();
                var ie = inner.GetEnumerator();

                var cts = new CancellationTokenDisposable();
                var d = Disposable.Create(cts, oe, ie);

                var current = default(TResult);
                var useOuter = true;
                var outerMap = new Dictionary <TKey, List <TOuter> >(comparer);
                var innerMap = new Dictionary <TKey, List <TInner> >(comparer);
                var q = new Queue <TResult>();

                var gate = new object();

                var f = default(Action <TaskCompletionSource <bool>, CancellationToken>);
                f = (tcs, ct) =>
                {
                    if (q.Count > 0)
                    {
                        current = q.Dequeue();
                        tcs.TrySetResult(true);
                        return;
                    }

                    var b = useOuter;
                    if (ie == null && oe == null)
                    {
                        tcs.TrySetResult(false);
                        return;
                    }
                    else if (ie == null)
                    {
                        b = true;
                    }
                    else if (oe == null)
                    {
                        b = false;
                    }
                    useOuter = !useOuter;

                    var enqueue = new Func <TOuter, TInner, bool>((o, i) =>
                    {
                        var result = default(TResult);
                        try
                        {
                            result = resultSelector(o, i);
                        }
                        catch (Exception exception)
                        {
                            tcs.TrySetException(exception);
                            return false;
                        }

                        q.Enqueue(result);
                        return true;
                    });

                    if (b)
                    {
                        oe.MoveNext(ct).Then(t =>
                        {
                            t.Handle(tcs, res =>
                            {
                                if (res)
                                {
                                    var element = oe.Current;
                                    var key = default(TKey);

                                    try
                                    {
                                        key = outerKeySelector(element);
                                    }
                                    catch (Exception exception)
                                    {
                                        tcs.TrySetException(exception);
                                        return;
                                    }

                                    var outerList = default(List <TOuter>);
                                    if (!outerMap.TryGetValue(key, out outerList))
                                    {
                                        outerList = new List <TOuter>();
                                        outerMap.Add(key, outerList);
                                    }

                                    outerList.Add(element);

                                    var innerList = default(List <TInner>);
                                    if (!innerMap.TryGetValue(key, out innerList))
                                    {
                                        innerList = new List <TInner>();
                                        innerMap.Add(key, innerList);
                                    }

                                    foreach (var v in innerList)
                                    {
                                        if (!enqueue(element, v))
                                        {
                                            return;
                                        }
                                    }

                                    f(tcs, ct);
                                }
                                else
                                {
                                    oe.Dispose();
                                    oe = null;
                                    f(tcs, ct);
                                }
                            });
                        });
                    }
                    else
                    {
                        ie.MoveNext(ct).Then(t =>
                        {
                            t.Handle(tcs, res =>
                            {
                                if (res)
                                {
                                    var element = ie.Current;
                                    var key = default(TKey);

                                    try
                                    {
                                        key = innerKeySelector(element);
                                    }
                                    catch (Exception exception)
                                    {
                                        tcs.TrySetException(exception);
                                        return;
                                    }

                                    var innerList = default(List <TInner>);
                                    if (!innerMap.TryGetValue(key, out innerList))
                                    {
                                        innerList = new List <TInner>();
                                        innerMap.Add(key, innerList);
                                    }

                                    innerList.Add(element);

                                    var outerList = default(List <TOuter>);
                                    if (!outerMap.TryGetValue(key, out outerList))
                                    {
                                        outerList = new List <TOuter>();
                                        outerMap.Add(key, outerList);
                                    }

                                    foreach (var v in outerList)
                                    {
                                        if (!enqueue(v, element))
                                        {
                                            return;
                                        }
                                    }

                                    f(tcs, ct);
                                }
                                else
                                {
                                    ie.Dispose();
                                    ie = null;
                                    f(tcs, ct);
                                }
                            });
                        });
                    }
                };

                return Create(
                    (ct, tcs) =>
                {
                    f(tcs, cts.Token);
                    return tcs.Task.UsingEnumerator(oe).UsingEnumerator(ie);
                },
                    () => current,
                    d.Dispose
                    );
            }));
        }
        public static IAsyncEnumerable <TSource> Intersect <TSource>(this IAsyncEnumerable <TSource> first, IAsyncEnumerable <TSource> second, IEqualityComparer <TSource> comparer)
        {
            if (first == null)
            {
                throw new ArgumentNullException("first");
            }
            if (second == null)
            {
                throw new ArgumentNullException("second");
            }
            if (comparer == null)
            {
                throw new ArgumentNullException("comparer");
            }

            return(Create(() =>
            {
                var e = first.GetEnumerator();

                var cts = new CancellationTokenDisposable();
                var d = Disposable.Create(cts, e);

                var mapTask = default(Task <Dictionary <TSource, TSource> >);
                var getMapTask = new Func <CancellationToken, Task <Dictionary <TSource, TSource> > >(ct =>
                {
                    if (mapTask == null)
                    {
                        mapTask = second.ToDictionary(x => x, comparer, ct);
                    }
                    return mapTask;
                });

                var f = default(Action <TaskCompletionSource <bool>, CancellationToken>);
                f = (tcs, ct) =>
                {
                    e.MoveNext(ct).Zip(getMapTask(ct), (b, _) => b).Then(t =>
                    {
                        t.Handle(tcs, res =>
                        {
                            if (res)
                            {
                                if (mapTask.Result.ContainsKey(e.Current))
                                {
                                    tcs.TrySetResult(true);
                                }
                                else
                                {
                                    f(tcs, ct);
                                }
                            }
                            else
                            {
                                tcs.TrySetResult(false);
                            }
                        });
                    });
                };

                return Create(
                    (ct, tcs) =>
                {
                    f(tcs, cts.Token);
                    return tcs.Task.UsingEnumerator(e);
                },
                    () => e.Current,
                    d.Dispose
                    );
            }));
        }
        public static IAsyncEnumerable <TSource> Concat <TSource>(this IAsyncEnumerable <TSource> first, IAsyncEnumerable <TSource> second)
        {
            if (first == null)
            {
                throw new ArgumentNullException("first");
            }
            if (second == null)
            {
                throw new ArgumentNullException("second");
            }

            return(Create(() =>
            {
                var switched = false;
                var e = first.GetEnumerator();

                var cts = new CancellationTokenDisposable();
                var a = new AssignableDisposable {
                    Disposable = e
                };
                var d = Disposable.Create(cts, a);

                var f = default(Action <TaskCompletionSource <bool>, CancellationToken>);
                f = (tcs, ct) => e.MoveNext(ct).Then(t =>
                {
                    t.Handle(tcs, res =>
                    {
                        if (res)
                        {
                            tcs.TrySetResult(true);
                        }
                        else
                        {
                            if (switched)
                            {
                                tcs.TrySetResult(false);
                            }
                            else
                            {
                                switched = true;

                                e = second.GetEnumerator();
                                a.Disposable = e;

                                f(tcs, ct);
                            }
                        }
                    });
                });

                return Create(
                    (ct, tcs) =>
                {
                    f(tcs, cts.Token);
                    return tcs.Task.UsingEnumerator(a);
                },
                    () => e.Current,
                    d.Dispose
                    );
            }));
        }
Example #7
0
        public static IAsyncEnumerable <TSource> Using <TSource, TResource>(Func <TResource> resourceFactory, Func <TResource, IAsyncEnumerable <TSource> > enumerableFactory) where TResource : IDisposable
        {
            if (resourceFactory == null)
            {
                throw new ArgumentNullException(nameof(resourceFactory));
            }
            if (enumerableFactory == null)
            {
                throw new ArgumentNullException(nameof(enumerableFactory));
            }

            return(CreateEnumerable(
                       () =>
            {
                var resource = resourceFactory();
                var e = default(IAsyncEnumerator <TSource>);

                try
                {
                    e = enumerableFactory(resource)
                        .GetEnumerator();
                }
                catch (Exception)
                {
                    resource.Dispose();
                    throw;
                }

                var cts = new CancellationTokenDisposable();
                var d = Disposable.Create(cts, resource, e);

                var current = default(TSource);

                return CreateEnumerator(
                    async ct =>
                {
                    bool res;
                    try
                    {
                        res = await e.MoveNext(cts.Token)
                              .ConfigureAwait(false);
                    }
                    catch (Exception)
                    {
                        d.Dispose();
                        throw;
                    }
                    if (res)
                    {
                        current = e.Current;
                        return true;
                    }
                    d.Dispose();
                    return false;
                },
                    () => current,
                    d.Dispose,
                    null
                    );
            }));
        }
Example #8
0
        public static IAsyncEnumerable <TSource> Using <TSource, TResource>(Func <TResource> resourceFactory, Func <TResource, IAsyncEnumerable <TSource> > enumerableFactory) where TResource : IDisposable
        {
            if (resourceFactory == null)
            {
                throw new ArgumentNullException("resourceFactory");
            }
            if (enumerableFactory == null)
            {
                throw new ArgumentNullException("enumerableFactory");
            }

            return(Create(() =>
            {
                var resource = resourceFactory();
                var e = default(IAsyncEnumerator <TSource>);

                try
                {
                    e = enumerableFactory(resource).GetEnumerator();
                }
                catch (Exception)
                {
                    resource.Dispose();
                    throw;
                }

                var cts = new CancellationTokenDisposable();
                var d = Disposable.Create(cts, resource, e);

                var current = default(TSource);

                return Create(
                    (ct, tcs) =>
                {
                    e.MoveNext(cts.Token).Then(t =>
                    {
                        t.Handle(tcs,
                                 res =>
                        {
                            if (res)
                            {
                                current = e.Current;
                                tcs.TrySetResult(true);
                            }
                            else
                            {
                                d.Dispose();
                                tcs.TrySetResult(false);
                            }
                        },
                                 ex =>
                        {
                            d.Dispose();
                            tcs.TrySetException(ex);
                        }
                                 );
                    });

                    return tcs.Task;
                },
                    () => current,
                    d.Dispose
                    );
            }));
        }
Example #9
0
        public static IAsyncEnumerable <TSource> TakeLast <TSource>(this IAsyncEnumerable <TSource> source, int count)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (count < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(count));
            }

            return(CreateEnumerable(
                       () =>
            {
                var e = source.GetEnumerator();

                var cts = new CancellationTokenDisposable();
                var d = Disposable.Create(cts, e);

                var q = new Queue <TSource>(count);
                var done = false;
                var current = default(TSource);

                var f = default(Func <CancellationToken, Task <bool> >);
                f = async ct =>
                {
                    if (!done)
                    {
                        if (await e.MoveNext(ct)
                            .ConfigureAwait(false))
                        {
                            if (count > 0)
                            {
                                var item = e.Current;
                                if (q.Count >= count)
                                {
                                    q.Dequeue();
                                }
                                q.Enqueue(item);
                            }
                        }
                        else
                        {
                            done = true;
                            e.Dispose();
                        }

                        return await f(ct)
                        .ConfigureAwait(false);
                    }
                    if (q.Count > 0)
                    {
                        current = q.Dequeue();
                        return true;
                    }
                    return false;
                };

                return CreateEnumerator(
                    f,
                    () => current,
                    d.Dispose,
                    e
                    );
            }));
        }