using System;
using System.Threading;

namespace System.Reactive
{
	public abstract class ObserverBase<T> : IObserver<T>, IDisposable
	{
		protected ObserverBase()
		{
			this._isStopped = 0;
		}

		public void OnNext(T value)
		{
			if (Volatile.Read(ref this._isStopped) == 0)
			{
				this.OnNextCore(value);
			}
		}

		protected abstract void OnNextCore(T value);

		public void OnError(Exception error)
		{
			if (error == null)
			{
				throw new ArgumentNullException("error");
			}
			if (Interlocked.Exchange(ref this._isStopped, 1) == 0)
			{
				this.OnErrorCore(error);
			}
		}

		protected abstract void OnErrorCore(Exception error);

		public void OnCompleted()
		{
			if (Interlocked.Exchange(ref this._isStopped, 1) == 0)
			{
				this.OnCompletedCore();
			}
		}

		protected abstract void OnCompletedCore();

		public void Dispose()
		{
			this.Dispose(true);
			GC.SuppressFinalize(this);
		}

		protected virtual void Dispose(bool disposing)
		{
			if (disposing)
			{
				Volatile.Write(ref this._isStopped, 1);
			}
		}

		internal bool Fail(Exception error)
		{
			if (Interlocked.Exchange(ref this._isStopped, 1) == 0)
			{
				this.OnErrorCore(error);
				return true;
			}
			return false;
		}

		private int _isStopped;
	}
}
