diff --git a/ICD.Common.Utils/Threading/SafeMutex.cs b/ICD.Common.Utils/Threading/SafeMutex.cs index 66c2798..97bdb53 100644 --- a/ICD.Common.Utils/Threading/SafeMutex.cs +++ b/ICD.Common.Utils/Threading/SafeMutex.cs @@ -1,4 +1,4 @@ -using System; +using System; #if SIMPLSHARP using Crestron.SimplSharp; #else @@ -12,8 +12,10 @@ namespace ICD.Common.Utils /// done with it. This class is an attempt to gracefully handle the ObjectDisposedExceptions /// we see on program termination, ocassionally causing the program to restart instead of stop. /// - public sealed class SafeMutex + public sealed class SafeMutex : IDisposable { + private bool _disposedValue; + #if SIMPLSHARP private readonly CMutex m_Mutex; #else @@ -21,8 +23,8 @@ namespace ICD.Common.Utils #endif /// - /// Constructor. - /// + /// Initializes a new instance of the class. + /// public SafeMutex() { #if SIMPLSHARP @@ -31,7 +33,20 @@ namespace ICD.Common.Utils m_Mutex = new Mutex(); #endif } - + + /// + /// Initializes a new instance of the class. + /// + /// + public SafeMutex(bool initiallyOwned) + { +#if SIMPLSHARP + m_Mutex = new CMutex(initiallyOwned); +#else + m_Mutex = new Mutex(initiallyOwned); +#endif + } + #region Methods /// @@ -46,7 +61,7 @@ namespace ICD.Common.Utils #if SIMPLSHARP return m_Mutex.WaitForMutex(timeout); #else - return m_Mutex.WaitOne(timeout); + return m_Mutex.WaitOne(timeout); #endif } catch (ObjectDisposedException) @@ -71,5 +86,50 @@ namespace ICD.Common.Utils } #endregion - } + + #region IDisposable + + private void Dispose(bool disposing) + { + if (!_disposedValue) + { + if (disposing) + { + // dispose managed state (managed objects) + try + { + // disposing of a mutex automatically releases it. Match that behavior + m_mutex.ReleaseMutex(); + m_Mutex.Dispose(); + } + catch (ObjectDisposedException) + { + // Releasing a disposed mutex in this case is valid behaviour + } + } + + // free unmanaged resources (unmanaged objects) and override finalizer + // set large fields to null + _disposedValue = true; + } + } + + + // override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources + // ~CaMutex() + // { + // // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + // Dispose(disposing: false); + // } + + /// + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + + #endregion + } }