Introduction
It wasn't too long ago that I needed to write an application where several threads were required. One of the threads in this application would be responsible for some shared resource, and the other threads would have to ask permission to gain temporary exclusive access to that shared resource. I knew that the resource did not need to be shared across multiple processes, so I wanted to avoid using expensive kernel objects. I decided to use a critical section to protect the resource where the several consuming threads would call the ::TryEnterCriticalSection()
API to ask for permission and if so granted gain exclusive access to the shared resource. The only one problem with this solution was ::TryEnterCriticalSection()
is only available on NT platforms, and I needed to support 9x.
The Solution
Several solutions to this problem ran through my mind. The first solution I considered was using a mutex object where the consuming threads would call the ::WaitForSingleObject()
API passing 0
to the second parameter of the function (indicating that the function should try to get the mutex, but not wait for it), and checking against a return value of WAIT_OBJECT_0
. The problem with this solution is it required use of the mutex kernel object, and it is a very expensive thing to switch from user to kernel mode. I decided to shelf that solution. After pondering a few other possibilities, I decided to write my own critical section class that allows for "try-enter" logic.
The CTryEnterCS class
CTryEnterCS
is the fruit of that effort. It's actually quite simple to use as there are only two public methods in the class. It operates 100% in user mode, making use of the ::InterlockedExchange()
and ::GetCurrentThreadId()
API's. Below is a description of the public methods:
bool TryEnter()
This locks the critical section for the current thread if no other thread already owns the critical section. If the current thread already owns the critical section (reentry), the current thread is allowed to pass. Returns true
if the critical section was entered; else false
.
bool Leave()
This releases (leaves) ownership of the critical section if the current thread entered it (using TryEnter()
). Returns true
if this was successful; else false
if this failed or the current thread did not own the critical section.
History
|
|
21-Sept-2002 |
Initial revision. |
|
|
25-Sept-2002 |
TryEnter now reference counts multiple entry from the same thread; Leave decrements the count and when zero releases the lock. |