Mutex in critical Section

if any exception occurs in critical section code then what sort of issue which we see in terms of synchronization objects?
Before and after the critical section code, Mutex is locked and unlocked. But if any exception occurs then the waiting thread will be waiting for resource to be freed as Mutex is not unlocked due to the execption.
So what needs to be done to get rid of this issue?
RAII

Use a class to handle locking and unlocking of the mutex. Lock in the ctor, unlock in the dtor.

When the exception is thrown, the stack will unwind, calling dtors for all allocated objects, thereby releasing the mutex.

boost and c++11 threads both provide RAII lock mechanisms for mutexes for this very reason. see unique_lock and lock_guard.


RAII RAII RAII. Always.
I got your point. But could you please explain with the help of any example code.

One more thing
as we know during stack unwinding destructors gets called for objects created on stack from try block till the place exception thrown. What happens to the memory created on heap. I think there would be a memory leak if not used smart pointer. Am I right? If I see the code below then during stack unwinding destructor would be called for x but not for y, right?
foo()
{
classA x;
classB *y = new classB()
}
Yes, there would be a memory leak, that's one of the reasons why smart pointers exist.
Last edited on
I got your point. But could you please explain with the help of any example code.


With C++11 threads, there are 2 classes of interest. std::mutex and std::lock_guard.

std::mutex is the actual mutex with lock() and unlock() functionality. However you probably should never call those routines directly. Instead, you use std::lock_guard, which is a RAII interface for locking/unlocking the mutex.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
std::mutex mymutex;

void bad_example()
{
   mymutex.lock();
   doStuff();   // BAD, if doStuff throws an exception, mymutex will not unlock!
      // potential for program deadlock
   mymutex.unlock();
}


void good_example()
{
   std::lock_guard lk( mymutex );  // lock_guard's ctor locks the mutex

   doStuff();
} // <- lock_guard's dtor unlocks the mutex 


The good example is good because no matter what doStuff does (even if it throws an exception), it is guaranteed that lk's destructor will be called, unlocking the mutex.



If I see the code below then during stack unwinding destructor would be called for x but not for y, right?


That is correct. Which, again, is why you RAII with smart pointers.

1
2
3
4
5
6
void foo()
{
  classA x;
  std::unique_ptr<classB> y( new classB() ); // RAII inside a unique_ptr

} // <- y's dtor will delete the pointer automatically. 
Many thanks to explain with example.
But as I asked earlier in meantioned code below
foo()
{
classA x;
classB *y = new classB()
}
If exception is thrown while object is getting created for classB, would still there be a memory leak when
1) some of the memebrs are initialised but not all
2) all members are initialized but because of some other thing exception is thrown
Topic archived. No new replies allowed.