The motivation to write this article came from Dr.Sai's excellent article "Working with CRITICAL_SECTION", so before reading this article one should first review that article.
This article explains how we can extend the custom critical section architecture to make it re-entrant.
To make it re-entrant we need to have a variable to save the recursion count,
m_lRecursionCount. The recursion count is local to the thread, is incremented each time that
EnterCriticalSection is called and keeps count of the number of times that
EnterCriticalSection is called in the thread.
In the above scenario, the expression
if (m_ThreadID == GetCurrentThreadId()) will evalute to
TRUE and increment the recursion count. Prior to that,
m_threadID is made equal to
GetCurrentThreadId() once either
interlockedincrement(&count) == 0 or
if (m_ThreadID != GetCurrentThreadId()) is necessary so that no other thread makes a call to
Leave() without making a call to
Enter(), in which case the call to
Leave should be ignored.
First a check of
m_lrecursivecount == 0 is made. If the recursion count is not zero, the recursion count is decremented, which means the thread needs to call
Leave some additional times before relinquishing control to other waiting threads.
If the statement
m_lrecursivecount == 0 evaluates to
TRUE, then we need to decrement the count and make a call to
SetEvent. Before making a call to
SetEvent we need to check that
InterlockedDecrement(&count) > 0. If
TRUE, a call to
SetEvent is made; if
FALSE, it is the last thread and hence there is no need to call
One should step through this program and examine every step until satisfied that it does work.
Finally thanks to Dr.Sai's article for helping me open the petals of knowledge. I am hoping for his comments on this article.