![]() |
General Programming »
Threads, Processes & IPC »
General
Intermediate
A "synchronized" statement for C++ like in JavaBy Achilleas MargaritisDesign and implementation of a "synchronized" C++ statement that works like the one in Java. |
C++, Windows, Visual-Studio, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
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 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:
lock() locks the critical section, and
unlock() unlocks the critical section. We are going to use critical sections, but any synchronization primitive applies.
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 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.
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; }
The macro exploits the nature of the for statement of C++ to do the following (in the presented order):
Using this way to code RAII has some advantages over the traditional method:
The synchronized macro is exception-safe, since it unlocks its mutex upon destruction.
| You must Sign In to use this message board. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
General
News
Question
Answer
Joke
Rant
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 |