Working with CRITICAL_SECTION

Environment: Visual Studio, All Windows platforms

-->

The Code

typedef class _MyCriticalSection
{
  long count;
  HANDLE Eventhandle;

public :
  _MyCriticalSection();
  void Enter();
  void Leave();
}MyCriticalSection;

That's it; everything is in the class!!!!!

The constructor creates an automatically resetting event and assigns it to EventHandle. Let us look at what goes on inside a general thread.

UINT func1(LPVOID lvoid)
{
  //WaitForSingleObject(handle,INFINITE);
  //This how you would use a CRITICAL_SECTION
Juhi.Enter();      //Simulates EnterCriticalSection(&cs);
  //EnterCriticalSection(&cs);
  for(intp=0;p<=4;p++)
    {
       cout<<"func1"<<endl;
    }
  AfxMessageBox("Func1");
  Juhi.Leave();    //Simulates LeaveCriticalSection(&cs);
                   //LeaveCriticalSection(&cs);
                   //This is how you would use a CRITICAL_SECTION
  return 1;
}

In Detail

Suppose there are 100 threads that call on enter, and say thread 77 is scheduled first, when enter executes, it will successfully validate the if condition namely if(InterlockedIncrement(&count)==1), (all the other threads will execute WaitForSingleObject(..) and wait infinitely) no matter when it is preempted by the OS, now this is the important point. One has to imagine the enter function getting preempted at all places and work out the logic for oneself.

So, other threads that call enter will fail the if(InterlockedIncrement(&count)==1) and block at that place (as they execute WaitForSingleObject(..)), until our thread 77 finishes the assigned job and calls the Leave() function. In the Leave() function, the count variable is decremented and Setevent(..) is called. From the remaining threads, one thread—say thread 45—gets to execute; in other words, its WaitForSingleObject(..) goes through. Because the event is automatically reset, none of the other threads go beyond the Enter() function. Simple, but amazing, no!!! Like that, all the rest of the threads execute one after the other.

One more point to be noted is that, although the kernel object event is used, if two threads do not clash, WaitForSingleObject(..) is never called and the thread never enters the Kernel mode so no time is wasted in entering the kernel mode and leaving it.

I have used three threads along with a MessageBox(..) inside each one of them, between Enter() and Leave(); until the First MessageBox is dismissed, no other thread will execute.

Well, this just the beginning. You can extend it across processeses. Imagine a critical section that works across process boundaries.

Downloads

Download demo project - 6 Kb