using System;

namespace Wayne.Lib
{
    /// <summary>
    /// Utility Base class that manages the disposable pattern. 
    /// Note that it only invokes the DoDispose when called from 
    /// explicit Dispose call. If called from finalizer, this is not called.
    /// </summary>
    public abstract class DisposableBase : IDisposable
    {
        private readonly object disposedLock = new object();
        private bool disposed;
        private bool disposeRunning;
        
        ~DisposableBase()
        {
            Dispose(false);
        }

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

        private void Dispose(bool disposing)
        {
            if (disposing)
            {
                lock (disposedLock)
                {
                    if (disposed || disposeRunning)
                    {
                        return;
                    }

                    disposeRunning = true;
                }

                try
                {
                    DoDispose();
                }
                finally
                {
                    lock (disposedLock)
                    {
                        disposed = true;
                        disposeRunning = false;
                    }
                }

            }
        }

        protected bool IsDisposed
        {
            get { return disposed || disposeRunning; }
        }

        /// <summary>
        /// Method that 
        /// </summary>
        protected abstract void DoDispose();
    }
}