Using a lock with recursive mutex for condition variable

Using a lock with recursive mutex for condition variable

Imagen de dulantha_f

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:

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

publicaciones de 14 / 0 nuevos
Último envío
Para obtener más información sobre las optimizaciones del compilador, consulte el aviso sobre la optimización.
Imagen de Sergey Kostrov

Hi,
Because 'ul' variable is not declared as 'tbb::mutex'.
Sergey

Imagen de Sergey Kostrov

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\

Imagen de dulantha_f

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?

Imagen de dulantha_f

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.

Imagen de Sergey Kostrov

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.

Imagen de Sergey Kostrov

>>...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.

Imagen de Sergey Kostrov

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 &'...

Imagen de Sergey Kostrov

>>...
>>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)
...

Imagen de Sergey Kostrov

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.

Imagen de Sergey Kostrov

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.

Imagen de Raf Schietekat

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.

Imagen de Sergey Kostrov

>>...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?

Imagen de Raf Schietekat

Any type with lock() and unlock() will do, so yes.

Inicie sesión para dejar un comentario.