public static IObservable <T> Merge <T>(this IObservable <IObservable <T> > sources, int maxConcurrent)
        {
            // this code is borrwed from RxOfficial(rx.codeplex.com)
            return(Observable.Create <T>(observer =>
            {
                var gate = new object();
                var q = new Queue <IObservable <T> >();
                var isStopped = false;
                var group = new CompositeDisposable();
                var activeCount = 0;

                var subscribe = default(Action <IObservable <T> >);
                subscribe = xs =>
                {
                    var subscription = new SingleAssignmentDisposable();
                    group.Add(subscription);
                    subscription.Disposable = xs.Subscribe(
                        x =>
                    {
                        lock (gate)
                            observer.OnNext(x);
                    },
                        exception =>
                    {
                        lock (gate)
                            observer.OnError(exception);
                    },
                        () =>
                    {
                        group.Remove(subscription);
                        lock (gate)
                        {
                            if (q.Count > 0)
                            {
                                var s = q.Dequeue();
                                subscribe(s);
                            }
                            else
                            {
                                activeCount--;
                                if (isStopped && activeCount == 0)
                                {
                                    observer.OnCompleted();
                                }
                            }
                        }
                    });
                };

                group.Add(sources.Subscribe(
                              innerSource =>
                {
                    lock (gate)
                    {
                        if (activeCount < maxConcurrent)
                        {
                            activeCount++;
                            subscribe(innerSource);
                        }
                        else
                        {
                            q.Enqueue(innerSource);
                        }
                    }
                },
                              exception =>
                {
                    lock (gate)
                        observer.OnError(exception);
                },
                              () =>
                {
                    lock (gate)
                    {
                        isStopped = true;
                        if (activeCount == 0)
                        {
                            observer.OnCompleted();
                        }
                    }
                }));

                return group;
            }));
        }
Beispiel #2
0
        public static IObservable <IList <T> > Buffer <T>(this IObservable <T> source, TimeSpan timeSpan, int count, IScheduler scheduler)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            if (count <= 0)
            {
                throw new ArgumentOutOfRangeException("count <= 0");
            }

            return(Observable.Create <IList <T> >(observer =>
            {
                var list = new List <T>();
                var gate = new object();
                var timerId = 0L;

                var d = new CompositeDisposable(2);
                var timerD = new SerialDisposable();

                // timer
                d.Add(timerD);
                Action createTimer = () =>
                {
                    var currentTimerId = timerId;
                    var timerS = new SingleAssignmentDisposable();
                    timerD.Disposable = timerS; // restart timer(dispose before)
                    timerS.Disposable = scheduler.Schedule(timeSpan, self =>
                    {
                        List <T> currentList;
                        lock (gate)
                        {
                            if (currentTimerId != timerId)
                            {
                                return;
                            }

                            currentList = list;
                            if (currentList.Count != 0)
                            {
                                list = new List <T>();
                            }
                        }
                        if (currentList.Count != 0)
                        {
                            observer.OnNext(currentList);
                        }
                        self(timeSpan);
                    });
                };

                createTimer();

                // subscription
                d.Add(source.Subscribe(x =>
                {
                    List <T> currentList = null;
                    lock (gate)
                    {
                        list.Add(x);
                        if (list.Count == count)
                        {
                            currentList = list;
                            list = new List <T>();
                            timerId++;
                            createTimer();
                        }
                    }
                    if (currentList != null)
                    {
                        observer.OnNext(currentList);
                    }
                }, observer.OnError, () =>
                {
                    lock (gate)
                    {
                        timerId++;
                    }
                    var currentList = list;
                    observer.OnNext(currentList);
                    observer.OnCompleted();
                }));

                return d;
            }));
        }
Beispiel #3
0
        public static IObservable <IList <TSource> > Buffer <TSource, TWindowBoundary>(this IObservable <TSource> source, IObservable <TWindowBoundary> windowBoundaries)
        {
            return(Observable.Create <IList <TSource> >(observer =>
            {
                var list = new List <TSource>();
                var gate = new object();

                var d = new CompositeDisposable(2);

                d.Add(source.Subscribe(Observer.Create <TSource>(
                                           x =>
                {
                    lock (gate)
                    {
                        list.Add(x);
                    }
                },
                                           ex =>
                {
                    lock (gate)
                    {
                        observer.OnError(ex);
                    }
                },
                                           () =>
                {
                    lock (gate)
                    {
                        var currentList = list;
                        list = new List <TSource>();    // safe
                        observer.OnNext(currentList);
                        observer.OnCompleted();
                    }
                }
                                           )));

                d.Add(windowBoundaries.Subscribe(Observer.Create <TWindowBoundary>(
                                                     w =>
                {
                    List <TSource> currentList;
                    lock (gate)
                    {
                        currentList = list;
                        if (currentList.Count != 0)
                        {
                            list = new List <TSource>();
                        }
                    }
                    if (currentList.Count != 0)
                    {
                        observer.OnNext(currentList);
                    }
                },
                                                     ex =>
                {
                    lock (gate)
                    {
                        observer.OnError(ex);
                    }
                },
                                                     () =>
                {
                    lock (gate)
                    {
                        var currentList = list;
                        list = new List <TSource>();    // safe
                        observer.OnNext(currentList);
                        observer.OnCompleted();
                    }
                }
                                                     )));

                return d;
            }));
        }
 public void Dispose()
 {
     disposables.Dispose();
     disposables = null;
 }