|
/////////////////////////////////////////////////////////////////////////////////
//
// Set of simple synchronization classes
//
// Copyright (c) 2003-2004
// Andrew Schetinin
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
//
// Permission to use or copy this software for any purpose is hereby granted
// without fee, provided the above notices are retained on all copies.
// Permission to modify the code and to distribute modified code is granted,
// provided the above notices are retained, and a notice that the code was
// modified is included with the above copyright notice.
//
// This software accompanies the article "Code that debugs itself"
// located at http://www.codeproject.com/debug/qafdebug.asp
//
// You are welcomed to report bugs, send comments and post code modifications
// to aschetinin@hotmail.com
//
/////////////////////////////////////////////////////////////////////////////////
///
/// @file CSyncCS.h "../Include/CSyncCS.h"
/// @brief Simple synchronization classes.
///
/// This file defines simple synchronization classes like critical
/// sections and mutexes.
#ifndef _QAFCSYNC_H_
#define _QAFCSYNC_H_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <wtypes.h>
#include "QAFDebug.h"
//
// Using of BEGIN_SYNC and END_SYNC:
//
// // Define it somewhere in your header file
// CAutoCS m_cs; // critical section object
//
// // And synchronize your code in CPP file
// BEGIN_SYNC( m_cs );
// .... do whatever you need ...
// END_SYNC;
//
/// Special define for organizing exception-safe synchronized blocks of code.
/// This is the start macro, it must be enclosed with END_SYNC
#define BEGIN_SYNC( sync_obj ) do { CAutoLockCS sync( sync_obj )
/// Special define for organizing exception-safe synchronized blocks of code.
/// This is the end macro
#define END_SYNC } while( FALSE )
/// A simple synchronization class, designed to be used as an automatic variable.
/// Once its instance is instanciated, it locks its visibility scope.
class CSyncCS
{
public:
/// Flag that the critical section object must be constructed or destroyed
enum CSOP { CS_NOP = 0, CS_CREATE = 1, CS_DESTROY = 2 };
/// Constructor creates and enters the critical section
CSyncCS( CRITICAL_SECTION * pcs, const CSOP csop = CS_NOP )
{
m_pcs = pcs;
m_csop = csop;
if( CS_CREATE == m_csop )
InitializeCriticalSection( m_pcs );
EnterCriticalSection( m_pcs );
}
/// Destructor leaves and destroys the critical section
~CSyncCS()
{
LeaveCriticalSection( m_pcs );
if( CS_DESTROY == m_csop )
DeleteCriticalSection( m_pcs );
}
private:
/// Critical section is used for synchronization
CRITICAL_SECTION * m_pcs;
/// Flag that the critical section object must be constructed or destroyed
CSOP m_csop;
};
/// Improved version of CSyncCS class
class CAutoCS
{
public:
/// Constructor creates the critical section
CAutoCS()
{
InitializeCriticalSection( &m_cs );
}
/// Destructor destroys the critical section
~CAutoCS()
{
DeleteCriticalSection( &m_cs );
}
/// Enter the critical section
void Lock()
{
EnterCriticalSection( &m_cs );
}
/// Leave the critical section
void Unlock()
{
LeaveCriticalSection( &m_cs );
}
private:
/// Critical section is used for synchronization
CRITICAL_SECTION m_cs;
};
/// Automatic locker for different synchronization objects.
template <class SyncClass>
class CLockCS
{
public:
/// Constructor locks the synchronization object
CLockCS( SyncClass &SyncObj ) : m_SyncObj(SyncObj)
{
m_SyncObj.Lock();
}
/// Destructor unlocks the synchronization object
~CLockCS()
{
m_SyncObj.Unlock();
}
private:
/// Reference to the synchronization object
SyncClass & m_SyncObj;
};
/// Shortcut for autolocking critical section.
typedef CLockCS<CAutoCS> CAutoLockCS;
/// Simple mutex class that is compatible to the CLockCS class.
class CMutex
{
public:
/// default constructor
CMutex() : m_hMutex(NULL), m_bOwned(false)
{
m_hMutex = CreateMutex( NULL, FALSE, NULL );
if( Q_ASSERT( NULL != m_hMutex ) )
m_bOwned = true;
}
/// default constructor
CMutex( LPCTSTR szMutexName ) : m_hMutex(NULL), m_bOwned(false)
{
m_hMutex = CreateMutex( NULL, FALSE, szMutexName );
if( Q_ASSERT( NULL != m_hMutex ) )
m_bOwned = true;
}
/// copy constructor
CMutex( HANDLE hMutex ) : m_hMutex(hMutex), m_bOwned(false)
{
Q_ASSERT( NULL != m_hMutex );
}
/// copy constructor
CMutex( const CMutex & obj ) : m_hMutex(obj.m_hMutex), m_bOwned(false)
{
Q_ASSERT( NULL != m_hMutex );
}
/// destructor
~CMutex()
{
if( m_bOwned )
{
Q_ASSERT( CloseHandle( m_hMutex ) );
m_hMutex = NULL;
}
}
/// get the handle of the mutex. this handle must not be closed
HANDLE GetHandle() const
{
return m_hMutex;
}
/// Enter the critical section
bool Lock( DWORD dwMilliseconds = INFINITE )
{
DWORD dwRet = WaitForSingleObject( m_hMutex, dwMilliseconds );
return Q_ASSERT( WAIT_OBJECT_0 == dwRet );
}
/// Leave the critical section
void Unlock()
{
Q_ASSERT( ReleaseMutex( m_hMutex ) );
}
protected:
private:
/// Mutex handle
HANDLE m_hMutex;
/// Flag if this handle is owned by the object
bool m_bOwned;
/// assignment operator
CMutex & operator=( const CMutex & obj )
{
if( this != &obj )
{
// copy the members
}
return *this;
}
};
///////////////////////////////////////////////
// END OF FILE
///////////////////////////////////////////////
#endif
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
Programming computers since entering the university in 1992, but dreaming of programming long time before putting hands on my first computer.
Experienced in cross-platform software development using C++ and Java, as well as rapid GUI development using Delphi/C#. Strong background in networking, relational databases, Web development, and mobile platforms.
Like playing guitar, visiting historical sites (not in the Internet, in the car
) and cooking meat with friends (sorry about vegetarians). Look for more information on
www.schetinin.com