Condition variable support in Intel® Threading Building Blocks

One feature present in the proposed C++ standard specification (e.g., N3092) threading support library, which we began supporting since Intel® Threading Building Blocks (Intel® TBB) 3.0, is condition variable.  As the C++1x proposal approaches the final approval, we expect using threads in conjunction with condition variables will become more popular.  For example, Microsoft has already been supporting condition variables natively since Windows Vista.  Until TBB 3.0, TBB used to provide only half of it (cf., std::thread – it used to be called tbb::tbb_thread).  The following code example shows how to use the TBB condition variable.  For a concise introduction to condition variables, see here or here.  

#include "tbb/compat/condition_variable"  
using namespace std;
condition_variable my_condition;
tbb::mutex my_mtx;
bool present = false;

void producer() {
    unique_lock<tbb::mutex> ul( my_mtx );
    present = true;
    my_condition.notify_one();
}

void consumer() {
    while( !present ) {
        unique_lock<tbb::mutex> ul( my_mtx );
        my_condition.wait( ul );
    }
}

From the onset, we made two design choices: 1) implement a subset of the functionalities offered by the C++1x std::condition_variable, and 2) use platform-dependent condition variable implementations wherever possible.  These decisions led us to leaving out condition_variable_any and supporting only tbb::mutex with the condition variable.  What these translate to is that the design is as close to section 30.5 of the C++1x draft as possible, but without relying on language features that are not part of the "current" C++ standard.  In the end, we ended up 1) dropping methods with rvalue references 2) dropping methods that require the C++1x <chrono> header, 3) using tbb::tick_count instead wherever possible, like we did for std::thread, and 4) including unique_lock_t, defer_lock_t, try_to_lock_t, adopt_lock_t, and lock_guard.  On platforms with pthread support, the implementation is just a thin wrapper around the pthread condition variable.  For Windows, TBB dynamically chooses between native condition variables (for >=Vista) and our own implementation (<=XP).

Since condition_variable is a part of the ISO C++1x specification, we decided to inject the names into the std namespace when a compiler in use does not support std::condition_variable or a user specifically asks for the TBB implementation.  By default, if the compiler is known to support std::condition_variable (for example, gcc 4.4 with -std=c++0x), std::condition_variable is used.  Otherwise, the internal TBB condition_variable and associated names are injected into the std namespace via 'using' clauses.  If a user wishes, she may set TBB_IMPLEMENT_CPP0X to a non-zero value to force injecting the TBB names into the std namespace.  Be warned that this may potentially cause name conflicts if for some reason the standard condition_variable is also included.  We advise users to pay extra attention when defining TBB_IMPLEMENT_CPP0X.

Finally, a few words on the exception support.  The c++1x condition variable should throw an std::system_error when something goes wrong or an unexpected event arises.  Initially, we decided to do the same by defining tbb::system_error.  Then, we realized the way tbb::system_error is defined makes it have different layouts in release and debug modes.  After a lengthy discussion, we agreed to throw std::runtime_error instead at the expense of a little bit of source portability.

So, where is it?  In order to use TBB condition variable, include 'tbb/compat/condition_variable' in your source file.  Enjoy.
For more complete information about compiler optimizations, see our Optimization Notice.