using System; #if SIMPLSHARP using Crestron.SimplSharp; namespace ICD.Common.Utils { /// /// CCriticalSection tends to get disposed before the parent is 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 partial class SafeCriticalSection { #if DEBUG private const int TIMEOUT = 5 * 60 * 1000; private readonly CMutex m_CriticalSection; #else private readonly CCriticalSection m_CriticalSection; #endif /// /// Constructor. /// public SafeCriticalSection() { #if DEBUG m_CriticalSection = new CMutex(); #else m_CriticalSection = new CCriticalSection(); #endif } #region Methods /// /// Block until ownership of the critical section can be obtained. /// public void Enter() { if (m_CriticalSection == null) return; try { #if DEBUG if (!m_CriticalSection.WaitForMutex(TIMEOUT)) throw new InvalidProgramException("Deadlock detected in program"); #else m_CriticalSection.Enter(); #endif } catch (ObjectDisposedException) { } } /// /// Release ownership of the critical section. /// public void Leave() { if (m_CriticalSection == null) return; try { #if DEBUG m_CriticalSection.ReleaseMutex(); #else m_CriticalSection.Leave(); #endif } catch (ObjectDisposedException) { } } /// /// Attempt to enter the critical section without blocking. /// /// /// True, calling thread has ownership of the critical section; otherwise, false. /// public bool TryEnter() { if (m_CriticalSection == null) return false; try { #if DEBUG return m_CriticalSection.WaitForMutex(0); #else return m_CriticalSection.TryEnter(); #endif } catch (ObjectDisposedException) { return false; } } #endregion } } #endif