Пример #1
0
        public static IObservable <T> Merge <T>(this IObservable <IObservable <T> > sources)
        {
            // this code is borrwed from RxOfficial(rx.codeplex.com)
            return(Observable.Create <T>(observer =>
            {
                var gate = new object();
                var isStopped = false;
                var m = new SingleAssignmentDisposable();
                var group = new CompositeDisposable()
                {
                    m
                };

                m.Disposable = sources.Subscribe(
                    innerSource =>
                {
                    var innerSubscription = new SingleAssignmentDisposable();
                    group.Add(innerSubscription);
                    innerSubscription.Disposable = innerSource.Subscribe(
                        x =>
                    {
                        lock (gate)
                            observer.OnNext(x);
                    },
                        exception =>
                    {
                        lock (gate)
                            observer.OnError(exception);
                    },
                        () =>
                    {
                        group.Remove(innerSubscription);           // modification MUST occur before subsequent check
                        if (isStopped && group.Count == 1)         // isStopped must be checked before group Count to ensure outer is not creating more groups
                        {
                            lock (gate)
                                observer.OnCompleted();
                        }
                    });
                },
                    exception =>
                {
                    lock (gate)
                        observer.OnError(exception);
                },
                    () =>
                {
                    isStopped = true;         // modification MUST occur before subsequent check
                    if (group.Count == 1)
                    {
                        lock (gate)
                            observer.OnCompleted();
                    }
                });

                return group;
            }));
        }
Пример #2
0
        static IDisposable InvokeRec3 <TState>(IScheduler scheduler, Pair <TState, Action <TState, Action <TState, DateTimeOffset> > > pair)
        {
            var group  = new CompositeDisposable(1);
            var gate   = new object();
            var state  = pair.First;
            var action = pair.Second;

            Action <TState> recursiveAction = null;

            recursiveAction = state1 => action(state1, (state2, dueTime1) =>
            {
                var isAdded = false;
                var isDone  = false;
                var d       = default(IDisposable);
                d           = scheduler.Schedule(state2, dueTime1, (scheduler1, state3) =>
                {
                    lock (gate)
                    {
                        if (isAdded)
                        {
                            group.Remove(d);
                        }
                        else
                        {
                            isDone = true;
                        }
                    }
                    recursiveAction(state3);
                    return(Disposable.Empty);
                });

                lock (gate)
                {
                    if (!isDone)
                    {
                        group.Add(d);
                        isAdded = true;
                    }
                }
            });

            recursiveAction(state);

            return(group);
        }
Пример #3
0
        public static IDisposable Schedule(this IScheduler scheduler, DateTimeOffset dueTime, Action <Action <DateTimeOffset> > action)
        {
            // InvokeRec3

            var group = new CompositeDisposable(1);
            var gate  = new object();

            Action recursiveAction = null;

            recursiveAction = () => action(dt =>
            {
                var isAdded = false;
                var isDone  = false;
                var d       = default(IDisposable);
                d           = scheduler.Schedule(dt, () =>
                {
                    lock (gate)
                    {
                        if (isAdded)
                        {
                            group.Remove(d);
                        }
                        else
                        {
                            isDone = true;
                        }
                    }
                    recursiveAction();
                });

                lock (gate)
                {
                    if (!isDone)
                    {
                        group.Add(d);
                        isAdded = true;
                    }
                }
            });

            group.Add(scheduler.Schedule(dueTime, recursiveAction));

            return(group);
        }
Пример #4
0
        public static IDisposable Schedule(this IScheduler scheduler, TimeSpan dueTime, Action <Action <TimeSpan> > action)
        {
            CompositeDisposable group = new CompositeDisposable(1);
            object gate            = new object();
            Action recursiveAction = null;

            recursiveAction = delegate()
            {
                action(delegate(TimeSpan dt)
                {
                    bool isAdded  = false;
                    bool isDone   = false;
                    IDisposable d = null;
                    object gate;
                    d = scheduler.Schedule(dt, delegate()
                    {
                        object gate2 = gate;
                        lock (gate2)
                        {
                            if (isAdded)
                            {
                                group.Remove(d);
                            }
                            else
                            {
                                isDone = true;
                            }
                        }
                        recursiveAction();
                    });
                    gate = gate;
                    lock (gate)
                    {
                        if (!isDone)
                        {
                            group.Add(d);
                            isAdded = true;
                        }
                    }
                });
            };
            group.Add(scheduler.Schedule(dueTime, recursiveAction));
            return(group);
        }
Пример #5
0
        public static IDisposable Schedule(this IScheduler scheduler, Action <Action> action)
        {
            // InvokeRec1
            CompositeDisposable group = new CompositeDisposable(1);
            object gate = new object();

            Action recursiveAction = null;

            recursiveAction = () => action(() =>
            {
                bool isAdded  = false;
                bool isDone   = false;
                IDisposable d = default(IDisposable);
                d             = scheduler.Schedule(() =>
                {
                    lock (gate)
                    {
                        if (isAdded)
                        {
                            group.Remove(d);
                        }
                        else
                        {
                            isDone = true;
                        }
                    }
                    recursiveAction();
                });

                lock (gate)
                {
                    if (!isDone)
                    {
                        group.Add(d);
                        isAdded = true;
                    }
                }
            });

            group.Add(scheduler.Schedule(recursiveAction));

            return(group);
        }
Пример #6
0
        public static IDisposable Schedule(this IScheduler scheduler, DateTimeOffset dueTime, Action <Action <DateTimeOffset> > action)
        {
            CompositeDisposable group = new CompositeDisposable(1);
            object gate            = new object();
            Action recursiveAction = null;

            recursiveAction = delegate
            {
                action(delegate(DateTimeOffset dt)
                {
                    bool isAdded  = false;
                    bool isDone   = false;
                    IDisposable d = null;
                    d             = scheduler.Schedule(dt, (Action) delegate
                    {
                        lock (gate)
                        {
                            if (isAdded)
                            {
                                group.Remove(d);
                            }
                            else
                            {
                                isDone = true;
                            }
                        }
                        recursiveAction();
                    });
                    lock (gate)
                    {
                        if (!isDone)
                        {
                            group.Add(d);
                            isAdded = true;
                        }
                    }
                });
            };
            group.Add(scheduler.Schedule(dueTime, recursiveAction));
            return(group);
        }
Пример #7
0
        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;
            }));
        }