예제 #1
0
        public static IObservable <T> SkipUntil <T, TOther>(this IObservable <T> source, IObservable <TOther> other)
        {
            return(Observable.Create <T>(observer =>
            {
                var sourceSubscription = new SingleAssignmentDisposable();
                var otherSubscription = new SingleAssignmentDisposable();

                var open = false;

                var gate = new object();

                sourceSubscription.Disposable = source.Synchronize(gate).Subscribe(
                    x =>
                {
                    if (open)
                    {
                        observer.OnNext(x);
                    }
                },
                    observer.OnError,
                    () =>
                {
                    if (open)
                    {
                        observer.OnCompleted();
                    }
                }
                    );

                otherSubscription.Disposable = other.Synchronize(gate).Subscribe(
                    x =>
                {
                    open = true;
                    otherSubscription.Dispose();
                },
                    observer.OnError
                    );

                return new CompositeDisposable(sourceSubscription, otherSubscription);
            }));
        }
        public static IObservable <IList <T> > Zip <T>(params IObservable <T>[] sources)
        {
            return(Observable.Create <IList <T> >(observer =>
            {
                var gate = new object();
                var length = sources.Length;
                var queues = new Queue <T> [length];
                for (int i = 0; i < length; i++)
                {
                    queues[i] = new Queue <T>();
                }
                var isDone = new bool[length];

                Action <int> dequeue = index =>
                {
                    lock (gate)
                    {
                        if (queues.All(x => x.Count > 0))
                        {
                            var result = queues.Select(x => x.Dequeue()).ToList();
                            observer.OnNext(result);
                            return;
                        }

                        if (isDone.Where((x, i) => i != index).All(x => x))
                        {
                            observer.OnCompleted();
                            return;
                        }
                    }
                };

                var subscriptions = sources
                                    .Select((source, index) =>
                {
                    var d = new SingleAssignmentDisposable();

                    d.Disposable = source.Subscribe(x =>
                    {
                        lock (gate)
                        {
                            queues[index].Enqueue(x);
                            dequeue(index);
                        }
                    }, ex =>
                    {
                        lock (gate)
                        {
                            observer.OnError(ex);
                        }
                    }, () =>
                    {
                        lock (gate)
                        {
                            isDone[index] = true;
                            if (isDone.All(x => x))
                            {
                                observer.OnCompleted();
                            }
                            else
                            {
                                d.Dispose();
                            }
                        }
                    });

                    return d;
                })
                                    .ToArray();

                return new CompositeDisposable(subscriptions)
                {
                    Disposable.Create(() =>
                    {
                        lock (gate)
                        {
                            foreach (var item in queues)
                            {
                                item.Clear();
                            }
                        }
                    })
                };
            }));
        }
예제 #3
0
 public void Dispose()
 {
     _disposable.Dispose();
 }
        public static IObservable <T> Amb <T>(this IObservable <T> source, IObservable <T> second)
        {
            return(Observable.Create <T>(observer =>
            {
                var choice = AmbState.Neither;
                var gate = new Object();

                var leftSubscription = new SingleAssignmentDisposable();
                var rightSubscription = new SingleAssignmentDisposable();

                leftSubscription.Disposable = source.Subscribe(x =>
                {
                    lock (gate)
                    {
                        if (choice == AmbState.Neither)
                        {
                            choice = AmbState.Left;
                            rightSubscription.Dispose();
                            // We can avoid lock every call but I'm not confident in AOT Safety.
                            // I'll try, check...
                            // left.Observer = observer;
                        }
                    }

                    if (choice == AmbState.Left)
                    {
                        observer.OnNext(x);
                    }
                }, ex =>
                {
                    lock (gate)
                    {
                        if (choice == AmbState.Neither)
                        {
                            choice = AmbState.Left;
                            rightSubscription.Dispose();
                        }
                    }

                    if (choice == AmbState.Left)
                    {
                        observer.OnError(ex);
                    }
                }, () =>
                {
                    lock (gate)
                    {
                        if (choice == AmbState.Neither)
                        {
                            choice = AmbState.Left;
                            rightSubscription.Dispose();
                        }
                    }

                    if (choice == AmbState.Left)
                    {
                        observer.OnCompleted();
                    }
                });

                rightSubscription.Disposable = second.Subscribe(x =>
                {
                    lock (gate)
                    {
                        if (choice == AmbState.Neither)
                        {
                            choice = AmbState.Right;
                            leftSubscription.Dispose();
                        }
                    }

                    if (choice == AmbState.Right)
                    {
                        observer.OnNext(x);
                    }
                }, ex =>
                {
                    lock (gate)
                    {
                        if (choice == AmbState.Neither)
                        {
                            choice = AmbState.Right;
                            leftSubscription.Dispose();
                        }
                    }

                    if (choice == AmbState.Right)
                    {
                        observer.OnError(ex);
                    }
                }, () =>
                {
                    lock (gate)
                    {
                        if (choice == AmbState.Neither)
                        {
                            choice = AmbState.Right;
                            leftSubscription.Dispose();
                        }
                    }

                    if (choice == AmbState.Right)
                    {
                        observer.OnCompleted();
                    }
                });

                return new CompositeDisposable {
                    leftSubscription, rightSubscription
                };
            }));
        }