Intel® oneAPI Threading Building Blocks
Ask questions and share information about adding parallelism to your applications when using this threading library.

using std::thread, std::mutex, etc. with tbb

Walter_D_
Beginner
1,598 Views

The tbb documentation says little about compatibility with c++11. There are some tbb features emulating c++11 features, such as threads and mutexes (and even illegally implementing them directly in namespace std), but it's less clear how to operate tbb under c++11. Nowhere does the documentation say whether tbb::thread is identical to std::thread (via typedef or similar) in case of c++11 or not. In particular, I want to know:

Is std::thread::get_id() behaving as expected when used from within a tbb::task (i.e. providing an identifier unique to the running thread)?

Can std::mutex be used in place of tbb::mutex and std::lock_guard<> in place of tbb::scoped_lock (when used from within a tbb::task)?

0 Kudos
5 Replies
RafSchietekat
Valued Contributor III
1,598 Views

It's not always fair to say that TBB is emulating C++11, because often the corresponding functionality was not defined before it was available from TBB. When appropriate, TBB does make some functionality from C++11 available in less recent environments. "Illegal" is a matter of perspective. :-)

tbb::tbb_thread was meant to emulate C++11 std::thread as a standard API (you can also use an O.S.-specific API), but precedence is given to the real std::thread (std::thread is a conditional typedef from tbb::tbb_thread into namespace std without C++11, but when C++11 is available they are different types). You should probably use the same compiler for the whole program so that std::thread always means the same thing, and then std::thread is the preferred way to use the class (whatever its origin).

std::thread::get_id() should behave as expected from wherever it is called. Again, don't rely on interoperability of values between code compiled with different compilers (you can always live dangerously...).

The mutex types are not interchangeable either, but TBB ones and C++11 ones can be used together in the same program (including inside TBB tasks). std::lock_guard() requires a BasicLockable mutex, and the Reference Manual documents that lock() and unlock() are available on most mutex types. It may be useful for the Reference Manual to explicitly say so in C++11 terminology.

(Correction 2013-05-10) preference->precedence

0 Kudos
Walter_D_
Beginner
1,598 Views

"Illegal" is a matter of perspective. :-) I was a bit pedantic, but it's not allowed (by the C++ standard) to add to namespace std.

but when C++11 is available they [the threads] are different types. std::thread::get_id() should behave as expected. Perhaps I should have asked more clearly: is there a one-to-one relation between tbb::thread and std::thread? (in other words: is there a unique map between tbb::this_thread::get_id() and std::this_thread::get_id()?)

0 Kudos
RafSchietekat
Valued Contributor III
1,598 Views

I think you can safely map the values, but they're not guaranteed to be identical because tbb::tbb_thread alias std::thread happens to go to, e.g., Pthreads and std::thread (the real one) does not declare any such relationship (as far as I know). The question is whether this matters at all? Are you going to use TBB code compiled with a pre-C++11 compiler together with code compiled with a C++11 compiler in such a way that the values can ever be compared directly, and is that not an easier thing to fix than trying to change or even just pin down TBB's behaviour?

(Added) Pedantry is often a good thing. It's only if you know the rules that you can make an informed decision to break them.

0 Kudos
Vladimir_P_1234567890
1,598 Views

Walter D. wrote:

The tbb documentation says little about compatibility with c++11. There are some tbb features emulating c++11 features, such as threads and mutexes (and even illegally implementing them directly in namespace std), but it's less clear how to operate tbb under c++11. rom within a tbb::task)?

17.6.4.2.1 Namespace std [namespace.std]

1 The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a
namespace within namespace std unless otherwise specified. A program may add a template specialization
for any standard library template to namespace std only if the declaration depends on a user-defined type
and the specialization meets the standard library requirements for the original template and is not explicitly
prohibited.

The behavior of a C++ program is undefined if it declares
— an explicit specialization of any member function of a standard library class template, or
— an explicit specialization of any member function template of a standard library class or class template,
or
— an explicit or partial specialization of any member class template of a standard library class or class
template.
A program may explicitly instantiate a template defined in the standard library only if the declaration
depends on the name of a user-defined type and the instantiation meets the standard library requirements
for the original template.

Hello Walter, why is it illegal? 

To use compat/thread you need to include special header and define special TBB_IMPLEMENT_CPP0X macro to enable tbb implementation of std::thread. If you are going to use different thread headers for different modules the behavior might be undefined but not illegal. 

For C++11 enabled compilers it is better to use compiler headers but not 'compat' ones.

--Vladimir

0 Kudos
RafSchietekat
Valued Contributor III
1,598 Views

Well, thread and condition_variable are not "unless otherwise specified", so program "behavior" is indeed "undefined".

It doesn't matter that the user has to do something special (#include "tbb/compat/thread"), it's still a compilation unit/program leading to "undefined behavior". And TBB_IMPLEMENT_CPP0X doesn't even have to be defined by the user (tbb_config.h will make a decision unless the user has already chosen a value). There's no such thing as "undefined but not illegal" (other than that you won't necessarily be fined or go to prison).

I understand why this was done, and why it is probably harmless. But it is still breaking a rule.

(Added) Sorry, "breaking a rule" is misleading. Strictly speaking, the Standard doesn't disallow this, it's just saying that, if you do this, you're on your own: the implementation is free to police or ignore it, or even to let the generated program post something embarrassing on Facebook (if it doesn't really care about its success in the marketplace).

(Additional small edits.)

0 Kudos
Reply