Пример #1
0
        /// <summary>
        /// Subscribes the given completable observer to this subject
        /// and relays/replays the terminal events of the subject.
        /// </summary>
        /// <param name="observer">The completable observer that wants to listen to the terminal events.</param>
        public void Subscribe(ISingleObserver <T> observer)
        {
            var inner = new InnerDisposable(observer, this);

            observer.OnSubscribe(inner);

            if (Add(inner))
            {
                if (inner.IsDisposed())
                {
                    Remove(inner);
                }
            }
            else
            {
                if (!inner.IsDisposed())
                {
                    var ex = Volatile.Read(ref error);
                    if (ex == null)
                    {
                        observer.OnSuccess(value);
                    }
                    else
                    {
                        observer.OnError(ex);
                    }
                }
            }
        }
        /// <summary>
        /// Subscribes the given completable observer to this subject
        /// and relays/replays the terminal events of the subject.
        /// </summary>
        /// <param name="observer">The completable observer that wants to listen to the terminal events.</param>
        public void Subscribe(ICompletableObserver observer)
        {
            var inner = new InnerDisposable(observer, this);

            observer.OnSubscribe(inner);

            if (Add(inner))
            {
                if (inner.IsDisposed())
                {
                    Remove(inner);
                }
            }
            else
            {
                if (!inner.IsDisposed())
                {
                    var ex = Volatile.Read(ref error);
                    if (ex == ExceptionHelper.TERMINATED)
                    {
                        observer.OnCompleted();
                    }
                    else
                    {
                        observer.OnError(ex);
                    }
                }
            }
        }
Пример #3
0
        void Remove(InnerDisposable inner)
        {
            for (; ;)
            {
                var a = Volatile.Read(ref observers);
                var n = a.Length;
                if (n == 0)
                {
                    break;
                }

                var j = -1;
                for (int i = 0; i < n; i++)
                {
                    if (a[i] == inner)
                    {
                        j = i;
                        break;
                    }
                }

                if (j < 0)
                {
                    break;
                }

                var b = default(InnerDisposable[]);
                if (n == 1)
                {
                    if (refCount)
                    {
                        if (Interlocked.CompareExchange(ref once, 1, 0) == 0)
                        {
                            this.error = new OperationCanceledException();
                            if (Interlocked.CompareExchange(ref observers, TERMINATED, a) == a)
                            {
                                DisposableHelper.Dispose(ref upstream);
                                break;
                            }
                        }
                        continue;
                    }
                    else
                    {
                        b = EMPTY;
                    }
                }
                else
                {
                    b = new InnerDisposable[n - 1];
                    Array.Copy(a, 0, b, 0, j);
                    Array.Copy(a, j + 1, b, j, n - j - 1);
                }
                if (Interlocked.CompareExchange(ref observers, b, a) == a)
                {
                    break;
                }
            }
        }
        public void Subscribe(ICompletableObserver observer)
        {
            var inner = new InnerDisposable(observer, this);

            observer.OnSubscribe(inner);

            if (Add(inner))
            {
                if (inner.IsDisposed())
                {
                    Remove(inner);
                }
            }
            else
            {
                if (!inner.IsDisposed())
                {
                    var ex = Volatile.Read(ref error);
                    if (ex == ExceptionHelper.TERMINATED)
                    {
                        observer.OnCompleted();
                    }
                    else
                    {
                        observer.OnError(ex);
                    }
                }
                return;
            }

            var src = Volatile.Read(ref source);

            if (src != null)
            {
                src = Interlocked.Exchange(ref source, null);
                if (src != null)
                {
                    var a = cancel;
                    cancel = null;
                    a?.Invoke(this);

                    src.Subscribe(this);
                }
            }
        }
        void Remove(InnerDisposable inner)
        {
            for (; ;)
            {
                var a = Volatile.Read(ref observers);
                var n = a.Length;
                if (n == 0)
                {
                    break;
                }

                var j = -1;
                for (int i = 0; i < n; i++)
                {
                    if (a[i] == inner)
                    {
                        j = i;
                        break;
                    }
                }

                if (j < 0)
                {
                    break;
                }

                var b = default(InnerDisposable[]);
                if (n == 1)
                {
                    b = EMPTY;
                }
                else
                {
                    b = new InnerDisposable[n - 1];
                    Array.Copy(a, 0, b, 0, j);
                    Array.Copy(a, j + 1, b, j, n - j - 1);
                }
                if (Interlocked.CompareExchange(ref observers, b, a) == a)
                {
                    break;
                }
            }
        }
Пример #6
0
        bool Add(InnerDisposable inner)
        {
            for (; ;)
            {
                var a = Volatile.Read(ref observers);
                if (a == TERMINATED)
                {
                    return(false);
                }

                var n = a.Length;
                var b = new InnerDisposable[n + 1];
                Array.Copy(a, 0, b, 0, n);
                b[n] = inner;
                if (Interlocked.CompareExchange(ref observers, b, a) == a)
                {
                    return(true);
                }
            }
        }