Advanced critical section






1.43/5 (4 votes)
Jul 8, 2002

130405

824
Advanced critical section which features TryLock and timeouts
Introduction
I had the need for a critical section which is easy to use and is independent of libraries like MFC.
Besides it should work on all Microsoft operating systems like Win9x/Me, WinNT/2K/XP and PocketPC/CE stuff.
So I wrote a class called CriticalSection
which fits my needs.
It implements functionality to Lock
and Unlock
an object (which a Win32 critical section provides too).
But there are two features "normal" critical sections don't provide:
- A
Lock
function which has an optional timeout - A
TryLock
function which is not available on Win9x/Me operating systems
Operations
You can either derive an object you want to synchronize from the CriticalSection
or make a CriticalSection
a member of an object. Whenever you enter code which needs to be protected call the Lock
or TryLock
function of the critical section.
Have a look at the code to see how it works:
// ******************************************************* // CriticalSection: Implements a critical section. // Provides a function similar to TryEnterCriticalSection // which is not available on Win9x/Me OSs // ******************************************************* class CriticalSection { public: // Construction/Destruction... CriticalSection(); virtual ~CriticalSection(); // Operations... // Locks this object. If another thread has ownership of // this object the function waits // until it's allowed to enter or the timeout elapses... inline bool Lock(const DWORD& dwMilliseconds = INFINITE) { if (::InterlockedCompareExchange(&m_lLockCount, 1, 0) == 0) { m_dwThreadID = ::GetCurrentThreadId(); return true; } if (m_dwThreadID == ::GetCurrentThreadId()) { ++m_lLockCount; return true; } if (::WaitForSingleObject(m_hEventUnlocked, dwMilliseconds) == WAIT_OBJECT_0) return Lock(0); return false; } // Unlocks this object... inline void Unlock() { if (m_dwThreadID != ::GetCurrentThreadId()) return; if (::InterlockedCompareExchange(&m_lLockCount, 0, 1) == 1) { m_dwThreadID = 0; ::PulseEvent(m_hEventUnlocked); } else --m_lLockCount; } // Tries to lock this object. // If not applicable "false" is returns immediately... inline bool TryLock() { return Lock(0); } private: // Internal data... DWORD m_dwThreadID; LONG m_lLockCount; HANDLE m_hEventUnlocked; };
The supplied sample application will show you how it works...
If you need help with this or have suggestions how to improve it or state bugs feel free to drop me an email. Updated versions may be found at www.nitrobit.com or www.codecommunity.com.