// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
#if !NO_PERF
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
namespace System.Reactive
{
///
/// Base class for implementation of query operators, providing performance benefits over the use of Observable.Create.
///
/// Type of the resulting sequence's elements.
abstract class Producer : IObservable
{
///
/// Publicly visible Subscribe method.
///
/// Observer to send notifications on. The implementation of a producer must ensure the correct message grammar on the observer.
/// IDisposable to cancel the subscription. This causes the underlying sink to be notified of unsubscription, causing it to prevent further messages from being sent to the observer.
public IDisposable Subscribe(IObserver observer)
{
if (observer == null)
throw new ArgumentNullException("observer");
var sink = new SingleAssignmentDisposable();
var subscription = new SingleAssignmentDisposable();
if (CurrentThreadScheduler.Instance.ScheduleRequired)
{
CurrentThreadScheduler.Instance.Schedule(this, (_, me) => subscription.Disposable = me.Run(observer, subscription, s => sink.Disposable = s));
}
else
{
subscription.Disposable = this.Run(observer, subscription, s => sink.Disposable = s);
}
return new CompositeDisposable(2) { sink, subscription };
}
///
/// Core implementation of the query operator, called upon a new subscription to the producer object.
///
/// Observer to send notifications on. The implementation of a producer must ensure the correct message grammar on the observer.
/// The subscription disposable object returned from the Run call, passed in such that it can be forwarded to the sink, allowing it to dispose the subscription upon sending a final message (or prematurely for other reasons).
/// Callback to communicate the sink object to the subscriber, allowing consumers to tunnel a Dispose call into the sink, which can stop the processing.
/// Disposable representing all the resources and/or subscriptions the operator uses to process events.
/// The observer passed in to this method is not protected using auto-detach behavior upon an OnError or OnCompleted call. The implementation must ensure proper resource disposal and enforce the message grammar.
protected abstract IDisposable Run(IObserver observer, IDisposable cancel, Action setSink);
}
}
#endif