Question

Can i put critical section amongst many if ,else conditions as I show below?

example 1

 somefunction()
    {
          EnterCriticalSection(&(g_variable)); 

          if (...)
          {
               if (...)
               {
               ...      

               }
               else
               {
                  ...
                   if (...) 
                   {...} 
                else if (...) 
                   {...}    

            LeaveCriticalSection(&(g_variable));

               }
          }
          else
          { 
                  ...      
          }


    }

or nest them like this:

example 2

EnterCriticalSection(&g_List); 
EnterCriticalSection(&g_Variable); 
...
LeaveCriticalSection(&g_List);  
LeaveCriticalSection(&g_Variable);

Thanks in advance for help.

Was it helpful?

Solution

There's something of a difference between what you can do and what you should do.

You can do what you show in your question. At least in my opinion, what you should do (since you're using C++) is use an RAII wrapper to automate getting your LeaveCriticalSection calls to match your EnterCriticalSection calls.

class crit_sect {
    CRITICAL_SECTION cs;

    void lock() { EnterCriticalSection(&cs); }
    void unlock() { LeaveCriticalSection(&cs); }
    friend class lock;

    crit_sect(crit_sect const &); /* = delete; */
    crit_sect &operator=(crit_sect const &other); /* = delete; */
public:
    crit_sect() { InitializeCriticalSection(&cs); }
    ~crit_sect() { DeleteCriticalSection(&cs); }
};

class lock {
    crit_sect &cs;
public:
    lock(crit_sect &c) : cs(c) { cs.lock(); }
    ~lock() { cs.unlock(); }
};

Using these, you'd have something like:

if (whatever) {
    lock list_lock(g_List);
    lock var_lock(g_Variable);

// ...

}

...and when execution leaves the scope in which the two locks were defined, the destructors will execute, automatically unlocking the critical sections. This is handy and convenient; if you're using exceptions, it becomes even more important, because it means if you exit the scope via an exception instead of via normal execution, the critical sections will still be unlocked.

OTHER TIPS

Short answer: Yes, you can. But it is easy to make mistakes with pairs of Enter/LeaveCriticalSection. Your own code shows that after taking the critical section in the top, there are code paths where the critical section is not released with a LeaveCriticalSection. One of the paths is where the else-block of the first if-statement is taken, but another, more insidious path is when some code in between throws an exception.

You tagged your question as C++; if C++11 is available, then there is an excellent alternative: the classes from the standard header , like recursive_mutex and lock_guard. Your code would look like this:

recursive_mutex g_variable;

someFunction()
{
    lock_guard<recursive_mutex> lock(g_variable);

    if (...)
        ...
    else
        ...
}

Now you have the guarantee that the mutex is released upon leaving someFunction(). And you have to type less, and your code is portable as well.

In example 1, this is bad habit. better threat critical section as a code block

EnterCriticalSection(&g_Variable);  
{  
   ....
}
LeaveCriticalSection(&g_Variable);

Even better, is to use scope CS class:

class CScopeCS{
  CRITICAL_SECTION& m_cs;
public:
  CScopeCS(CRITICAL_SECTION& cs):m_cs(cs){
     EnterCriticalSection(cs);
  }
  ~CScopeCS(){
     LeaveCriticalSection(m_cs);
  }
}

and when exit from critical section block, it will call the destructor automatically.

{
  CScopeCS scopeLock(g_cs);
  ....
}//end of critical section

In example 2, it will work like you wrote it, but you better leave the last one first:

EnterCriticalSection(&g_List); 
EnterCriticalSection(&g_Variable); 
...
LeaveCriticalSection(&g_Variable);
LeaveCriticalSection(&g_List);  

But you must take the two critical sections in the same order in your code to prevent deadlocks. (i.e. first g_List then g_Variable) if you already entered the g_Variable and want to enter also to the g_List you must leave g_Variable and take them in order.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top