Example #1
0
        private void Unsubscribe(SubjectDisposable observer)
        {
            for (; ;)
            {
                var a = Volatile.Read(ref _observers);
                var n = a.Length;
                if (n == 0)
                {
                    break;
                }

                var j = Array.IndexOf(a, observer);

                if (j < 0)
                {
                    break;
                }

                SubjectDisposable[] b;
                if (n == 1)
                {
                    b = Array.Empty <SubjectDisposable>();
                }
                else
                {
                    b = new SubjectDisposable[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;
                }
            }
        }
Example #2
0
        /// <summary>
        /// Subscribes an observer to the subject.
        /// </summary>
        /// <param name="observer">Observer to subscribe to the subject.</param>
        /// <returns>Disposable object that can be used to unsubscribe the observer from the subject.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="observer"/> is null.</exception>
        public override IDisposable Subscribe(IObserver <T> observer)
        {
            if (null == observer)
            {
                throw new ArgumentNullException(nameof(observer));
            }

            var disposable = default(SubjectDisposable);

            for (; ;)
            {
                var subscribers = Volatile.Read(ref observers);

                if (subscribers == DISPOSED)
                {
                    exception = null;
                    ThrowDisposed();

                    break;
                }

                if (subscribers == TERMINATED)
                {
                    var ex = exception;

                    if (ex != null)
                    {
                        observer.OnError(ex);
                    }
                    else
                    {
                        observer.OnCompleted();
                    }

                    break;
                }

                if (disposable == null)
                {
                    disposable = new SubjectDisposable(this, observer);
                }

                var n = subscribers.Length;
                var b = new SubjectDisposable[n + 1];

                Array.Copy(subscribers, 0, b, 0, n);

                b[n] = disposable;

                if (Interlocked.CompareExchange(ref observers, b, subscribers) == subscribers)
                {
                    return(disposable);
                }
            }

            return(Disposable.Empty);
        }
Example #3
0
        public IDisposable Subscribe(IObserver <T> observer)
        {
            if (observer == null)
            {
                throw new ArgumentNullException(nameof(observer));
            }

            var disposable = default(SubjectDisposable);

            for (; ;)
            {
                var observers = Volatile.Read(ref _observers);

                if (observers == Disposed)
                {
                    _exception = null;
                    ThrowDisposed();

                    break;
                }

                if (observers == Terminated)
                {
                    var ex = _exception;

                    if (ex != null)
                    {
                        observer.OnError(ex);
                    }
                    else
                    {
                        observer.OnCompleted();
                    }

                    break;
                }

                disposable ??= new SubjectDisposable(this, observer);

                var n = observers.Length;
                var b = new SubjectDisposable[n + 1];

                Array.Copy(observers, 0, b, 0, n);

                b[n] = disposable;

                if (Interlocked.CompareExchange(ref _observers, b, observers) == observers)
                {
                    return(disposable);
                }
            }

            return(Disposable.Empty);
        }