Click here to Skip to main content
6,905,855 members and growing! (20,387 online)
Email Password   helpLost your password?
General Programming » Threads, Processes & IPC » General     Intermediate

A "synchronized" statement for C++ like in Java

By Achilleas Margaritis

Design and implementation of a "synchronized" C++ statement that works like the one in Java.
C++, Windows, Visual-Studio, Dev
Posted:18 Dec 2005
Views:37,141
Bookmarked:19 times
printPrint   add Share
      Discuss Discuss   Broken Article?Report  
21 votes for this article.
Popularity: 5.14 Rating: 3.89 out of 5
3 votes, 14.3%
1
3 votes, 14.3%
2
2 votes, 9.5%
3
4 votes, 19.0%
4
9 votes, 42.9%
5

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:

  • it initializes the critical section upon construction,
  • it deletes the critical section,
  • the method lock() locks the critical section, and
  • the method unlock() unlocks the critical section.

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:

  • it locks the mutex upon construction, and
  • it unlocks the mutex upon destruction.

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:

  • it makes the code more readable,
  • it helps avoiding declaration of lock variables, and
  • it ties the code to be synchronized with the synchronization scope.

Notes

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

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Achilleas Margaritis


Member

Occupation: Software Developer (Senior)
Location: Greece Greece

Other popular Threads, Processes & IPC articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 13 of 13 (Total in Forum: 13) (Refresh)FirstPrevNext
GeneralHere is my version. Pinmemberpedro.alves9:02 20 Dec '05  
GeneralRe: Here is my version. Pinmemberpedroalves0:18 26 Dec '05  
GeneralRe: Here is my version. Pinmemberpedroalves0:21 26 Dec '05  
GeneralC++ is not Java ... It's better Pinmember[Deep]Xor22:18 19 Dec '05  
GeneralNeeds Improvement PinmemberDavid Patrick1:02 19 Dec '05  
GeneralRe: Needs Improvement PinmemberAchilleas Margaritis2:22 19 Dec '05  
GeneralRe: Needs Improvement PinmemberRoland Pibinger12:50 19 Dec '05  
GeneralC++ versions ? PinmemberRobert Bielik23:57 18 Dec '05  
GeneralRe: C++ versions ? PinmemberAchilleas Margaritis2:14 19 Dec '05  
GeneralRe: C++ versions ? PinmemberPeter Ritchie6:35 20 Dec '05  
GeneralC++ versions ! PinmemberRobert Bielik21:31 20 Dec '05  
GeneralRe: C++ versions ! Pinmemberpedro.alves8:29 21 Dec '05  
You could also put this in global include file:

#define for if(0){}else for


Cheers,

Pedro Alves

GeneralRe: C++ versions ! PinmemberPeter Ritchie9:24 23 Dec '05  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+PgUp/PgDown to switch pages.

PermaLink | Privacy | Terms of Use
Last Updated: 18 Dec 2005
Editor: Smitha Vijayan
Copyright 2005 by Achilleas Margaritis
Everything else Copyright © CodeProject, 1999-2010
Web20 | Advertise on the Code Project