Win32 Thread Synchronization, Part 2: Helper Classes

Introduction

This article is a continuation of the Thread Synchronization Helper Classes article. Part 1 contained a general discussion of Win32 threading, talked about typical problems with sharing data between threads, and offered some solutions using critical sections and mutexes. You also saw some typical pitfalls that often occur when using these Win32 synchronization objects.

Part 2 introduces thread synchronization helper classes, their implementation, and includes sample projects.

Synchronization Library: Overview and Purpose

This library provides implementations for critical section, mutex, and single write, multiple reader classes. In addition, it also provides an autolock class to provide auto lock and unlock for the synchronization classes.

The classes described herein are designed to help reduce the common programming errors associated with natively using critical sections and mutexes as discussed in Part 1.

Library Classes

The critical section and mutex classes are merely thin wrappers to the Win32 APIs that handle synchronization object initialization/creation, locking, unlocking, and cleanup. Proper object initialization and cleanup is ensured during class construction and destruction. Each class implements two public Lock and Unlock methods that call the underlying lock and unlock native APIs appropriate for each object type.

Critical section class

The CLockableCS class is a thin critical section wrapper that performs critical section initialization in the constructor and cleanup in the destructor. The lock and unlock public methods can be called directly or implicitly by using the CAutolockT class.

class CLockableCS
{
// Methods
public:
   // Ctor / Dtor
   inline CLockableCS() throw()  { InitializeCriticalSection( &m_CS ); }
   inline ~CLockableCS() throw() { DeleteCriticalSection( &m_CS ); }

   // Lock / Unlock
   inline void Lock() throw()    { EnterCriticalSection( &m_CS ); }
   inline void Unlock() throw()  { LeaveCriticalSection( &m_CS ); }

// Attributes
private:
   CRITICAL_SECTION m_CS;        // Internal Critical Section
};

Mutex class

The CLockableMutex class is a thin mutex wrapper that creates a named mutex in the constructor and performs cleanup in the destructor. The lock method takes a timeout parameter to specify how long to wait to acquire the lock. If the lock method errors or timesout before a lock is acquired, the class throws CAutoLockExc or CAutoLockTimeoutExc exceptions. The lock and unlock public methods can be called directly or implicitly by using the CAutoLockT class.

class CLockableMutex
{
public:
   inline CLockableMutex( LPCTSTR szName ) throw()
      : m_hMutex( ::CreateMutex( NULL, FALSE, szName ) )
   {
   }

   inline ~CLockableMutex() throw()
   {
      if(m_hMutex) ::CloseHandle( m_hMutex );
   }

   inline void Lock( DWORD dwTimeout )
   {
      DWORD dwWaitResult = ::WaitForSingleObject( m_hMutex, dwTimeout );
      switch( dwWaitResult )
      {
      case WAIT_OBJECT_0:
         break;
      case WAIT_TIMEOUT:
         throw CAutoLockTimeoutExc( dwTimeout );
         break;
      default:
         throw CAutoLockExc( dwWaitResult, ::GetLastError() );
      }
   }

   inline void Unlock() throw()
   {
      ::ReleaseMutex( m_hMutex );
   }

private:
   HANDLE m_hMutex;              // Mutex Handle
};

Single writer, multiple reader class

The single writer, multiple reader (SWMR) class is used for cases where there are infrequent writes, but concurrent read operations. For this type of usage, the CLockableSWMR class will be more performant than using the critical section class because the CLockableCS doesn’t distinguish between reading and writing and locks for both, whereas the SWMR class only locks for write operations, so multiple read threads can still access simultaneously. The CLockableSWMR class is for single process use only. The source for the CLockableSWMR class is several pages long. In the interest of saving space, please refer to the source listing in the AutoLock.h file located in the article’s source code.

CAutoLockT class

The CAutoLockT class is a templated class used to provide scope-based locking/unlocking for any of the CLockableXXX classes as well as any class derived from the CComObjectRoot ATL class.

template<class T>
class CAutoLockT
{
// Attributes
private:
   T* m_pObject;                 // the locked object

// Ctor/dtor
public:
   // Critical Section Ctor
   inline CAutoLockT( T* pObject ) throw()
      : m_pObject( pObject )
   {
      ATLASSERT( NULL != pObject );
      m_pObject->Lock();
   }

    // Mutex Ctor
   inline CAutoLockT( T* pObject, DWORD dwTimeout )
      : m_pObject(pObject)
   {
      ATLASSERT( NULL != pObject );
      m_pObject->Lock( dwTimeout );
   }

   // SRMR Ctor
   inline CAutoLockT( T* pObject,
                      const _LOCKTYPE uLockType,
                      LPCTSTR szOperation = NULL ) throw()
                      : m_pObject(pObject)
   {
      ATLASSERT( NULL != pObject );
      m_pObject->Lock( uLockType, szOperation );
   }

   // Ctor
   inline ~CAutoLockT()
   {
      m_pObject->Unlock();
   }
};

More by Author

Must Read