Example #1
0
        /// <summary>
        /// Subscribes an observer to the subject.
        /// </summary>
        public IDisposable Subscribe(IObserver <T> observer)
        {
            if (observer == null)
            {
                throw new ArgumentNullException("observer");
            }

            var subscription = new RemovableDisposable(this, observer);
            var group        = new CompositeDisposable(subscription);
            var myq          = default(Queue <Timestamped <Notification <T> > >);

            lock (this.observers)
            {
                Trim(scheduler.Now);
                myq = new Queue <Timestamped <Notification <T> > >(q);
                qs.Add(myq);
            }
            group.Add(scheduler.Schedule(self =>
            {
                var ts = default(Timestamped <Notification <T> >);
                lock (this.observers)
                {
                    if (!subscription.IsStopped && myq.Count > 0)
                    {
                        ts = myq.Dequeue();
                    }
                    else
                    {
                        qs.Remove(myq);
                        observers.Add(observer);
                        subscription.IsStarted = true;
                    }
                }

                if (ts.Value != null)
                {
                    ts.Value.Accept(observer);
                    self();
                }
            }));
            return(group);
        }
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 IDisposable Subscribe(IObserver <T> observer)
        {
            if (observer == null)
            {
                throw new ArgumentNullException("observer");
            }

            var so = new ScheduledObserver <T>(_scheduler, observer);

            var n = 0;

            var subscription = new RemovableDisposable(this, so);

            lock (_gate)
            {
                CheckDisposed();

                //
                // Notice the v1.x behavior of always calling Trim is preserved here.
                //
                // This may be subject (pun intended) of debate: should this policy
                // only be applied while the sequence is active? With the current
                // behavior, a sequence will "die out" after it has terminated by
                // continue to drop OnNext notifications from the queue.
                //
                // In v1.x, this behavior was due to trimming based on the clock value
                // returned by scheduler.Now, applied to all but the terminal message
                // in the queue. Using the IStopwatch has the same effect. Either way,
                // we guarantee the final notification will be observed, but there's
                // no way to retain the buffer directly. One approach is to use the
                // time-based TakeLast operator and apply an unbounded ReplaySubject
                // to it.
                //
                // To conclude, we're keeping the behavior as-is for compatibility
                // reasons with v1.x.
                //
                Trim(_stopwatch.Elapsed);
                _observers = _observers.Add(so);

                n = _queue.Count;
                foreach (var item in _queue)
                {
                    so.OnNext(item.Value);
                }

                if (_error != null)
                {
                    n++;
                    so.OnError(_error);
                }
                else if (_isStopped)
                {
                    n++;
                    so.OnCompleted();
                }
            }

            so.EnsureActive(n);

            return(subscription);
        }