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

Design and implementation of a &quot;synchronized&quot; C++ statement that works like the one in Java.

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):

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:

How it works

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

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.

test part: the lock variable is tested and found to be true: the code inside the loop is executed.

increment part: the lock variable's internal flag is set to false.

test part: the lock variable is tested and found to be false: the loop exits.

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.

Since there is actually a Mutex in win32 and it is signficantly different from the Critical Section class in terms of implementation, functionality and performance characteristics it is very misleading to call the class Mutex when in fact it does NOT use a Mutex. It's a minor issue, but none-the-less may cause confusion for future maintance programmers.

Since all it does is set the boolean flag, in effect the scope of the synchronization lasts for the life of the Lock object created for the for loop .. the life span of this object is dependent upon compiler behavior and may extend beyond the scope of the specified synchronization block itself.

3. Speaking of the boolean flag ... was it really necessary ?

I like what you are trying to do, and I think you have a pretty good "first shot" ... I'm sure after a few revisions this will be a fine alternative to the current approach of just declaring the lock object inside the curly braces for the block which is to be synchronized ( I agree, the Java approach is more readable in some circumstances )

"We need less government, not more. The idea that we can become a better society by having a bigger rule book is ridiculous, regardless of who is trying to change the rules" - Doug Goulden

Well, it is just demo code. I prefer the short name Mutex instead of the long CriticalSection, also because a critical section is a mutual-exclusion object as well.

David Patrick wrote:

Shouldnt the Lock::setUnlock() function actually unlock the mutex ?

Since all it does is set the boolean flag,

No, the function 'setUnlock' should not unlock the mutex. If it did, then it would be named 'unlock'. By using 'set' as a prefix, it is made clear that it has a different function. It could be named 'setUnlockFlag', if you like.

David Patrick wrote:

the scope of the synchronization lasts for the life of the Lock object created for the for loop

Indeed, and that's the correct design: RAII dictates a resource be released upon destruction of the Lock object.

David Patrick wrote:

the life span of this object is dependent upon compiler behavior

Microsoft compilers up to VC6 may have a problem. But as I am replying in the other post, that's Microsoft's problem, and not mine: they did not implement the VC++ 98 standard correctly. GCC has no problem.

David Patrick wrote:

I like what you are trying to do, and I think you have a pretty good "first shot"

Well, feel free to modify it as needed. It was just a short sample anyway.