Skip to main content
Email Password   helpLost your password?

Introduction

This article shows how to code a synchronized statement in C++ that works in a similar way to Java. The target of this code is to make a piece of code like the following, compilable and executable in C++:

synchronized(myMutex)
{
    //TODO put synchronized code here

}

The Mutex class

The following piece of code presents a mutex class with lock/unlock semantics (common in many libraries):

//mutex class

class Mutex
{
public:
    //the default constructor

    Mutex()
    {
        InitializeCriticalSection(&m_criticalSection);
    }

    //destructor

    ~Mutex()
    {
        DeleteCriticalSection(&m_criticalSection);
    }

    //lock

    void lock()
    {
        EnterCriticalSection(&m_criticalSection);
    }

    //unlock

    void unlock()
    {
        LeaveCriticalSection(&m_criticalSection);
    }

private:
    CRITICAL_SECTION m_criticalSection;
};

There is nothing particularly special for the above class:

We are going to use critical sections, but any synchronization primitive applies.

The Lock class

In order to be consistent with the C++ established code practices, we need a special class for implementing the RAII (Resource Acquisition Is Initialisation) pattern. The following piece of code shows such a class:

//synchronization controller object

class Lock
{
public:
    //the default constructor

    Lock(Mutex &mutex) : m_mutex(mutex), m_locked(true)
    {
        mutex.lock();
    }

    //the destructor

    ~Lock()
    {
        m_mutex.unlock();
    }

    //report the state of locking when used as a boolean

    operator bool () const
    {
        return m_locked;
    }

    //unlock

    void setUnlock()
    {
        m_locked = false;        
    }

private:
    Mutex &m_mutex;
    bool m_locked;
};

Things to note for this class:

Using the above class is pretty straightforward:

Mutex mutex1;
...
Lock lock1(mutex1);
//synchronized code here

The "synchronized" macro

The synchronized statement can be coded as a macro like this:

#define synchronized(M)  for(Lock M##_lock = M; M##_lock; M##_lock.setUnlock())

where, the parameter M is the mutex variable to use for locking.

Example of using the "synchronized" macro

The following piece of code shows how to use the synchronized macro: it coordinates two threads that print the alphabet in the standard output. Without synchronization, the output is not correct:

//thread count

int thread_count = 0;

//mutex

Mutex mutex1;

//example thread

DWORD CALLBACK thread_proc(LPVOID params)
{
    for(int i = 0; i < 10; ++i)
    {
        synchronized(mutex1)
        {
            for(char c = 'A'; c <= 'Z'; ++c)
            {
                cout << c;
            }
            cout << endl;
        }
    }
    thread_count--;
    return 0;
}

//main

int main()
{
    thread_count = 2;
    CreateThread(0, 0, thread_proc, 0, 0, 0);
    CreateThread(0, 0, thread_proc, 0, 0, 0);
    while (thread_count) Sleep(0);
    getchar();
    return 0;
}

How it works

The macro exploits the nature of the for statement of C++ to do the following (in the presented order):

  1. initialization part: a local lock variable is defined that locks the given mutex; the lock variable contains an internal flag which is set to true.
  2. test part: the lock variable is tested and found to be true: the code inside the loop is executed.
  3. increment part: the lock variable's internal flag is set to false.
  4. test part: the lock variable is tested and found to be false: the loop exits.
  5. exit part: the lock variable is destroyed, unlocking the mutex.

Advantages over classic RAII

Using this way to code RAII has some advantages over the traditional method:

Notes

The synchronized macro is exception-safe, since it unlocks its mutex upon destruction.

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralHere is my version. Pin
pedro.alves
9:02 20 Dec '05  
GeneralRe: Here is my version. Pin
pedroalves
0:18 26 Dec '05  
GeneralRe: Here is my version. Pin
pedroalves
0:21 26 Dec '05  
GeneralC++ is not Java ... It's better Pin
[Deep]Xor
22:18 19 Dec '05  
GeneralNeeds Improvement Pin
David Patrick
1:02 19 Dec '05  
GeneralRe: Needs Improvement Pin
Achilleas Margaritis
2:22 19 Dec '05  
GeneralRe: Needs Improvement Pin
Roland Pibinger
12:50 19 Dec '05  
GeneralC++ versions ? Pin
Robert Bielik
23:57 18 Dec '05  
GeneralRe: C++ versions ? Pin
Achilleas Margaritis
2:14 19 Dec '05  
GeneralRe: C++ versions ? Pin
Peter Ritchie
6:35 20 Dec '05  
GeneralC++ versions ! Pin
Robert Bielik
21:31 20 Dec '05  
GeneralRe: C++ versions ! Pin
pedro.alves
8:29 21 Dec '05  
GeneralRe: C++ versions ! Pin
Peter Ritchie
9:24 23 Dec '05  


Last Updated 18 Dec 2005 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2009