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

Using a lock with recursive mutex for condition variable

dulantha_f
Beginner
1,507 Views

Hi, 

I was wondering if there was any reason why the condition_variable won't accept a unique lock with a recursive mutex. Compiler gives an error when I try to do that:

[cpp]recursive_mutex rec_mutex;

unique_lock ul(rec_mutex);

condition_variable condVar;

condVar.wait(ul); // <-- compile error saying ul needs tbb::mutex and not tbb::recursive_mutex

[/cpp]

0 Kudos
13 Replies
SergeyKostrov
Valued Contributor II
1,507 Views
Hi, Because 'ul' variable is not declared as 'tbb::mutex'. Sergey
0 Kudos
SergeyKostrov
Valued Contributor II
1,507 Views
This is a follow up. >>...I was wondering if there was any reason why the condition_variable won't accept a unique lock with a recursive mutex... 'unique_lock' is a template class and you need to specify a type 'mutex'. Please take a look at a 'condition_variable' source file located at: ..\[ TBBDIR ]\Include\tbb\compat\
0 Kudos
dulantha_f
Beginner
1,507 Views
ahh it's a template class. Got it. Thank you. But if I don't provide the type for template it defaults to tbb::mutex? That's why in the above code I get the compile error?
0 Kudos
dulantha_f
Beginner
1,507 Views
The last comment I made probably doesn't make sense. The problem is not the unique lock, the problem is the condition_variable. I just noticed the website removes the template defintions. So I put them in brackets. Hopefully there's no confusion. [cpp] tbb::recursive_mutex rmutex; std::unique_lock(tbb::recursive_mutex) ul1(rmutex); std::condition_variable condVar; condVar.wait(ul1); // <-- compile error here[cpp] But if I make the unique_lock (tbb::mutex) then it compiles fine. I get 2 different error messages on Win and LX. So my question is why the condition_variable only accepts tbb::mutexe and not tbb::recursive_mutex? Thank you.
0 Kudos
SergeyKostrov
Valued Contributor II
1,507 Views
Hi, >>But if I don't provide the type for template it defaults to tbb::mutex? That's a good question. Since you had a compilation error it didn't. About 2 years ago I had a similar issue with a template class. That is, Microsoft C++ compiler allowed to compile the template with, I would say, a "weaker" declaration. However, MinGW C++ compiler did not and it means that MinGW is a very strict compiler when it comes to declarations. I could provide a small example if interested, >>...That's why in the above code I get the compile error? Yes.
0 Kudos
SergeyKostrov
Valued Contributor II
1,507 Views
>>...I just noticed the website removes the template defintions. So I put them in brackets. Hopefully there's no confusion. It happened again. Honestly, I posted so many messages regarding that problem with arrow-left and arrow-right characters and I don't know what to tell you now. >>...But if I make the unique_lock (tbb::mutex) then it compiles fine. I get 2 different error messages on Win and LX. So my question is >>why the condition_variable only accepts tbb::mutexe and not tbb::recursive_mutex? Let me take a look at a declaration of 'tbb::recursive_mutex' template class.
0 Kudos
SergeyKostrov
Valued Contributor II
1,506 Views
Here is a summary of my investigation: 1. This is how a 'wait' method is declared in a 'condition_variable' class: ... void wait( unique_lock< mutex > & lock ); ... 2. These two classes are declared as follows: ** mutex.h ** ... class mutex { public: //! Construct unacquired mutex. mutex() { ... }; and ** recursive_mutex.h ** ... class recursive_mutex { public: //! Construct unacquired recursive_mutex. recursive_mutex() { ... }; and the 'recursive_mutex' class is not based on 'mutex'. That is, something like this: ... class recursive_mutex : public mutex { public: ... }; Since there is no a C++ operator '=' to convert from type 'recursive_mutex' to type 'mutex' a C++ compiler reports some error: Error C2664: ...cannot convert parameter 1 from 'tbb::recursive_mutex' to 'tbb::mutex &'...
0 Kudos
SergeyKostrov
Valued Contributor II
1,507 Views
>>... >>recursive_mutex rec_mutex; >>unique_lock ul(rec_mutex); >>condition_variable condVar; >>condVar.wait(ul); >>... I verified the code with Microsoft C++ compiler and it did not compile it when left-arrow mutex right-arrow not used: Compiling... ... ..\common\prttests.cpp(42814) : error C2955: 'tbb::interface5::unique_lock' : use of class template requires template argument list ..\include\tbb\compat\condition_variable(113) : see declaration of 'tbb::interface5::unique_lock' ..\common\prttests.cpp(42814) : error C2514: 'tbb::interface5::unique_lock' : class has no constructors ..\include\tbb\compat\condition_variable(113) : see declaration of 'tbb::interface5::unique_lock' ..\common\prttests.cpp(42816) : error C2664: 'void tbb::interface5::condition_variable::wait(tbb::interface5::unique_lock &)' : cannot convert parameter 1 from 'tbb::interface5::unique_lock' to 'tbb::interface5::unique_lock &' with [ M=tbb::mutex ] ScaLibTestApp - 3 error(s), 0 warning(s) ...
0 Kudos
SergeyKostrov
Valued Contributor II
1,507 Views
Here are three small test-cases I tried with Microsoft C++ compiler: ... // Test-Case 1 { mutex reg_mutex; unique_lock[ mutex ] ul( reg_mutex ); condition_variable condVar; condVar.wait( ul ); } // Test-Case 2 { recursive_mutex rec_mutex; unique_lock[ mutex ] ul( rec_mutex ); condition_variable condVar; condVar.wait( ul ); // Error C2664: 'tbb::interface5::unique_lock::unique_lock(tbb::mutex &)' : // cannot convert parameter 1 from 'tbb::recursive_mutex' to 'tbb::mutex &' } // Test-Case 3 { recursive_mutex rec_mutex; unique_lock[ recursive_mutex ] ul( &rec_mutex ); condition_variable condVar; condVar.wait( ul ); // Error C2664: 'void tbb::interface5::condition_variable::wait(tbb::interface5::unique_lock &)' : // cannot convert parameter 1 from 'tbb::interface5::unique_lock' to 'tbb::interface5::unique_lock &' // with // [ // M=tbb::mutex // ] // and // [ // M=tbb::recursive_mutex // ] // and // [ // M=tbb::mutex // ] } ... It is clear that another method like: ... void wait( unique_lock< recursive_mutex > & lock ); ... is needed in the 'condition_variable' class.
0 Kudos
SergeyKostrov
Valued Contributor II
1,507 Views
And final answer to your question: >>...I was wondering if there was any reason why the condition_variable won't accept a unique lock with a recursive mutex... Another method like: ... void wait( unique_lock< recursive_mutex > & lock ); ... is needed in the 'condition_variable' class.
0 Kudos
RafSchietekat
Valued Contributor III
1,507 Views
Note that condition_variable, like thread, is intentionally implemented exactly as described by the new C++ standard (which seems to have adopted it from boost, a known incubator for new standard features), so this limitation is not unique to TBB (as you will readily find). The problem at hand is that TBB has not also provided compatibility support for condition_variable_any.
0 Kudos
SergeyKostrov
Valued Contributor II
1,507 Views
>>...The problem at hand is that TBB has not also provided compatibility support for condition_variable_any. Thanks for the note! Does it mean that condition_variable_any could work with mutex and recursive_mutex?
0 Kudos
RafSchietekat
Valued Contributor III
1,507 Views
Any type with lock() and unlock() will do, so yes.
0 Kudos
Reply