/*** *lock.h * * Copyright (c) Microsoft Corporation. All rights reserved. * *Purpose: lock class for automatically acquiring/releasing * the monitor lock on managed types. * * [Public] * ****/ #pragma once #if !defined (_INC_MSCLR_LOCK) #ifndef __cplusplus_cli #error ERROR: msclr libraries are not compatible with /clr:oldSyntax #endif /* __cplusplus_cli */ #include #if !defined (_M_CEE_SAFE) #include #endif /* !defined (_M_CEE_SAFE) */ namespace msclr { // The lock_when enumeration is used to defer the lock object // from taking the lock. enum lock_when { lock_later }; ref class lock { private: System::Object ^ m_object; bool m_locked; template value struct is_not { typedef int __dont_use_this_type__; }; template value struct is_not { }; public: // By default, take the lock immediately with an infinite timeout. // Accept an optional timespan (in milliseconds) and throw on failure or timeout. template lock( T ^ _object) : m_object( _object ), m_locked( false ) { // ensure that T is not a ReaderWriterLock. typedef is_not::__dont_use_this_type__ _Diagnostic; acquire(System::Threading::Timeout::Infinite); } template lock( T ^ _object, int _timeout ) : m_object( _object ), m_locked( false ) { // ensure that T is not a ReaderWriterLock. typedef is_not::__dont_use_this_type__ _Diagnostic; acquire( _timeout ); } // By default, take the lock immediately within the specified timespan // and throw on failure or timeout. template lock( T ^ _object, System::TimeSpan _timeout ) : m_object( _object ), m_locked( false ) { // ensure that T is not a ReaderWriterLock. typedef is_not::__dont_use_this_type__ _Diagnostic; acquire( _timeout ); } // If you use the "lock_later" enumeration, it causes lock // to defer taking the lock. template lock( T ^ _object, lock_when ) : m_object( _object ), m_locked( false ) { // ensure that T is not a ReaderWriterLock. typedef is_not::__dont_use_this_type__ _Diagnostic; } #if !defined (_M_CEE_SAFE) template lock( gcroot _object) : m_object( _object ), m_locked( false ) { // ensure that T is not a ReaderWriterLock. typedef is_not::__dont_use_this_type__ _Diagnostic; acquire(System::Threading::Timeout::Infinite); } template lock( gcroot _object, int _timeout ) : m_object( _object ), m_locked( false ) { // ensure that T is not a ReaderWriterLock. typedef is_not::__dont_use_this_type__ _Diagnostic; acquire( _timeout ); } // By default, take the lock immediately within the specified timespan // and throw on failure or timeout. template lock( gcroot _object, System::TimeSpan _timeout ) : m_object( _object ), m_locked( false ) { // ensure that T is not a ReaderWriterLock. typedef is_not::__dont_use_this_type__ _Diagnostic; acquire( _timeout ); } // If you use the "lock_later" enumeration, it causes lock // to defer taking the lock. template lock( gcroot _object, lock_when ) : m_object( _object ), m_locked( false ) { // ensure that T is not a ReaderWriterLock. typedef is_not::__dont_use_this_type__ _Diagnostic; } #endif /* !defined (_M_CEE_SAFE) */ // release the lock if it is not currently held ~lock() { release(); } // Check to see if this lock object is currently holding the lock bool is_locked() { return m_locked; } // Check to see if this lock object is currently holding the lock operator _detail_class::_safe_bool() { return is_locked() ? _detail_class::_safe_true : _detail_class::_safe_false; } // disallow explicit comparisons to _safe_bool template bool operator==( T t ) { // ensure that T is not a _safe_bool. typedef is_not::__dont_use_this_type__ _Diagnostic; return m_object == t; } template bool operator!=( T t ) { // ensure that T is not a _safe_bool. typedef is_not::__dont_use_this_type__ _Diagnostic; return m_object != t; } // Take the lock within the specified timespan, or with an infinite // timespan if none is specified. Throw on timeout void acquire( int _timeout ) { if( ! m_locked ) { System::Threading::Monitor::TryEnter( m_object, _timeout, m_locked ); if( ! m_locked ) { static const long _hresult_wait_timeout = 0x80070102; throw System::Runtime::InteropServices::Marshal::GetExceptionForHR( _hresult_wait_timeout ); } } } void acquire() { if( ! m_locked ) { System::Threading::Monitor::TryEnter( m_object, System::Threading::Timeout::Infinite, m_locked ); if( ! m_locked ) { static const long _hresult_wait_timeout = 0x80070102; throw System::Runtime::InteropServices::Marshal::GetExceptionForHR( _hresult_wait_timeout ); } } } // Take the lock within the specified timespan. // throw on timeout void acquire( System::TimeSpan _timeout ) { if( ! m_locked ) { System::Threading::Monitor::TryEnter( m_object, _timeout, m_locked ); if( ! m_locked ) { static const long _hresult_wait_timeout = 0x80070102; throw System::Runtime::InteropServices::Marshal::GetExceptionForHR( _hresult_wait_timeout ); } } } // Try to take the lock within the specified timespan. In the case // of timeout, return false. bool try_acquire( int _timeout ) // noexcept, but error C2353 prohibits on managed classes { if( ! m_locked ) { System::Threading::Monitor::TryEnter( m_object, _timeout, m_locked ); if( ! m_locked ) { return false; } } return true; } // Try to take the lock within the specified timespan. In the case // of timeout, return false. bool try_acquire( System::TimeSpan _timeout ) // noexcept, but error C2353 prohibits on managed classes { if( ! m_locked ) { System::Threading::Monitor::TryEnter( m_object, _timeout, m_locked ); if( ! m_locked ) { return false; } } return true; } // Release the lock if it is currently held void release() { if( m_locked ) { System::Threading::Monitor::Exit( m_object ); m_locked = false; } } }; } #define _INC_MSCLR_LOCK #endif /* !defined (_INC_MSCLR_LOCK) */