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?
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:
CSingleLock
so recursion will cause issues.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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With