Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMutex::Lock vs. CSingleLock::Lock

I've been tapped to support some legacy code, and I'm seeing some things that cause me to scratch my head in confusion. In some sections of code, I see that a class instance uses a CMutex instance to synchronize method execution. For instance

class CClassA : public CObject
{
public:
   void DoSomething();

private:
   CMutex m_mutex;
}

void CClassA::DoSomething()
{
   m_mutex.Lock();

   //...logic...

   m_mutex.Unlock();
}

Elsewhere in the same project I find that the code is using a CSingleLock

class CClassB : public CObject
{
public:
   void DoSomething();

private:
   CCriticalSection m_crit;
}

void CClassB::DoSomething()
{
   CSingleLock lock(&m_crit);
   lock.Lock();

   //...logic...

   lock.Unlock();
}

After reviewing MSDN documentation for synchronization, it would appear that CClassB is implementing the advised method, but it isn't clear to me what the danger is in the implementation used by CClassA. As far as I can tell, the only difference between the two methods is that CSingleLock has the benefit of RAII, so the lock is automatically released when execution exits scope. Are there any other benefits / drawbacks to either implementation?

like image 279
JadeMason Avatar asked May 19 '11 18:05

JadeMason


1 Answers

In general mutexes can be used to control thread access across processes via a named mutex while critical sections are only for synchronizing thread access in the same process space.

Neither of these classes truly get the benefit of RAII without wrapping them because in that case you would never need to explicitly call lock or unlock. Take for example this little bit of pseudo code using a boost mutex lock ...

void DoSomething()
{
  // construction acquires lock on mutex
  boost::scoped_lock lock(&aBoostMutex);

  // ...

} // end scope - object is destroyed and lock is released

Now I'd argue you should avoid CMutex, CCritalSection, CSemaphore, and CEvent because the implementations are somewhat broken or at the very least inferior to other available libraries like boost. For example:

  • Determining between a timeout from an abandoned mutex is impossible because the implementation checks return value only not the reason.
  • No reentrant locks using CSingleLock so recursion will cause issues.
  • Inability to have a named event between processes

Depending on what you are tasked with you might have the opportunity to move away from the MFC wrappers on windows API and either implement your own atomic locks or use something like boost or C++0x features like std::mutex which not only are better implementations but provide cross-platform support.

like image 70
AJG85 Avatar answered Sep 28 '22 03:09

AJG85