Scenario:
I have a condition_variable based wait and signal mechanism. This works! But I need a little more than just the classic wait and signal mechanism. I need to be able to do a timed wait as well as an infinite wait "on the same condition_variable
". Hence, I created a wrapper class around a condition_variable
which takes care of the spurious wake up issue as well. Following is the code for that:
Code:
// CondVarWrapper.hpp
#pragma once
#include <mutex>
#include <chrono>
#include <condition_variable>
class CondVarWrapper {
public:
void Signal() {
std::unique_lock<std::mutex> unique_lock(cv_mutex);
cond_var_signalled = true;
timed_out = false;
unique_lock.unlock();
cond_var.notify_one();
}
bool WaitFor(const std::chrono::seconds timeout) {
std::unique_lock<std::mutex> unique_lock(cv_mutex);
timed_out = true;
cond_var.wait_for(unique_lock, timeout, [this] {
return cond_var_signalled;
});
cond_var_signalled = false;
return (timed_out == false);
}
bool Wait() {
std::unique_lock<std::mutex> unique_lock(cv_mutex);
timed_out = true;
cond_var.wait(unique_lock, [this] {
return cond_var_signalled;
});
cond_var_signalled = false;
return (timed_out == false);
}
private:
bool cond_var_signalled = false;
bool timed_out = false;
std::mutex cv_mutex;
std::condition_variable cond_var;
};
// main.cpp
#include "CondVarWrapper.hpp"
#include <iostream>
#include <string>
#include <thread>
int main() {
CondVarWrapper cond_var_wrapper;
std::thread my_thread = std::thread([&cond_var_wrapper]{
std::cout << "Thread started" << std::endl;
if (cond_var_wrapper.WaitFor(std::chrono::seconds(10))) {
std::cout << "Thread stopped by signal from main" << std::endl;
} else {
std::cout << "ERROR: Thread stopping because of timeout" << std::endl;
}
});
std::this_thread::sleep_for(std::chrono::seconds(3));
// Uncomment following line to see the timeout working
cond_var_wrapper.Signal();
my_thread.join();
}
Question:
Above code is good but I think there is one problem? Would I really be able to do a wait
as as well do a wait_for
on the same condition_variable
? What if a thread has acquired cv_mutex
by calling CondVarWrapper::Wait()
and this one never returned for some reason. And then another thread comes in calling CondVarWrapper::WaitFor(std::chrono::seconds(3))
expecting to return out if it does not succeed in 3 seconds. Now, this second thread would not be able to return out of WaitFor
after 3 seconds isnt it? In fact it wouldn't ever return. Because the condition_variable
wait is a timed wait but not the lock on cv_mutex
. Am I correct or Am I wrong in understanding here?
If I am correct above then I need to replace std::mutex cv_mutex
with a std::timed_mutex cv_mutex
and do a timed_wait in CondVarWrapper::WaitFor
and do a infinite wait on CondVarWrapper::Wait
? Or are there any better/easier ways of handling it?
Aucun commentaire:
Enregistrer un commentaire