Friday, May 7, 2010

Language-like Synchronized Block

In "A 'synchronized' statement for C++ like in Java" Achilleas Margaritis presents a synchronized macro that emulates the Java behavior.
  synchronized(l) {
    foo();
    return bar();
  } 
I have adapted the macro to use Boost.Thread as follows:
#define synchronized(MUTEX) \
  if (bool _stop_ = false) {} else \
  for (boost::scoped_guard<boost::mutex> _lock_(MUTEX); 
      !_stop_; _stop_ = true)
How it works?
The macro exploits the nature of the if and for statements of C++ to do the following (in the presented order):
  1. The if condition introduces a new _stop_ variable on the scope of if statement, which is the initialized to false, so the else part will be executed.
  2. for initialization part: a local _lock_ variable is defined that locks the given mutex.
  3. test part: the !_stop_ expression is found to be true: the code inside the loop is executed.
  4. increment part: the _stop_ variable is set to true.
  5. test part: the !_stop_ expression is found to be false: the loop exits.
  6. exit part: the _lock_ variable is destroyed, unlocking the mutex.
The advantage over the initial proposal:
  • no need to wrap a locker class to add extra functions to set the flag neither a conversion operator to bool.
Advantages over classic RAI:
  • it makes the code more language-like, pretending synchronized to be a keyword,
  • it helps avoiding declaration of the auxiliary lock variable, and
  • it ties the code to be synchronized with the next statement either simple or compound.
For example no need to add curly brackets to synchronize a sentence as in
  {
    boost::scoped_guard<boost::mutex> _lock_(l);
    ++cnt;
  }
Just prefix the sentence with
  synchronized(l) ++cnt;

With exception-based timed locks we can define synchronized_until and synchronized_for. Both can throw a timeout_exception
  synchronized_until(l,abs) ++cnt;

No comments:

Post a Comment