Reputation: 8229
I am using a std::condition_variable
combined with a std::unique_lock
like this.
std::mutex a_mutex;
std::condition_variable a_condition_variable;
std::unique_lock<std::mutex> a_lock(a_mutex);
a_condition_variable.wait(a_lock, [this] {return something;});
//Do something
a_lock.unlock();
It works fine. As I understand, std::condition_variable
accepts a std::unique_lock
for it to wait. But, I am trying to combine it with std::lock_guard
but not able to.
My question is: Is it possible to replace std::unique_lock
with a std::lock_guard
instead ? This can relieve me from manually unlocking the lock every time I use it.
Upvotes: 14
Views: 7436
Reputation: 201
Any call to wait()
on a condition variable will always need to lock()
and unlock()
the underlying mutex
. Since the wrapper lock_guard<>
does not provide these functions, it can never be used with wait()
.
Still you could write your own simple mutex wrapper based on lock_guard<>
, and add the 2 necessary methods. Additionally you would have to use condition_variable_any
, which accepts any lock/mutex with a lock()/unlock() interface:
#include <mutex>
template<typename _mutex_t>
class my_lock_guard
{
public:
explicit my_lock_guard(_mutex_t & __m) : __mutex(__m)
{ __mutex.lock(); }
my_lock_guard(_mutex_t & __m, std::adopt_lock_t) : __mutex(__m)
{ } // calling thread owns mutex
~my_lock_guard()
{ __mutex.unlock(); }
void lock()
{ __mutex.lock(); }
void unlock()
{ __mutex.unlock(); }
my_lock_guard(const my_lock_guard &) = delete;
my_lock_guard& operator=(const my_lock_guard &) = delete;
private:
_mutex_t & __mutex;
};
And then:
#include <condition_variable>
...
std::mutex m;
my_lock_guard<std::mutex> lg(m);
std::condition_variable_any cva;
cva.wait(lg, [] { return something;});
// do something ...
...
Upvotes: 7
Reputation: 9090
No, a std::unique_lock
is needed if it is used with std::condition_variable
. std::lock_guard
may have less overhead, but it cannot be used with std::condition_variable
.
But the std::unique_lock
doesn't need to be manually unlocked, it also unlocks when it goes out of scope, like std::lock_guard
. So the waiting code could be written as:
std::mutex a_mutex;
std::condition_variable a_condition_variable;
{
std::unique_lock<std::mutex> a_lock(a_mutex);
a_condition_variable.wait(a_lock, [this] {return something;});
//Do something
}
See http://en.cppreference.com/w/cpp/thread/unique_lock
Upvotes: 12
Reputation: 21936
Impossible, but you don’t actually need that.
std::unique_lock
automatically unlocks itself in destructor, if it was locked.
Upvotes: 6