同一个条件变量的定时等待和无限等待?
Timed waiting and infinite waiting on the same condition variable?
场景:
我有一个基于 condition_variable 的等待和信号机制。这行得通!但我需要的不仅仅是 classic 等待和信号机制。我需要能够进行定时等待和无限等待 "on the same condition_variable
"。因此,我围绕 condition_variable
创建了一个包装器 class,它也处理虚假唤醒问题。以下是相关代码:
代码:
// 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();
}
问题:
上面的代码很好,但我认为有一个问题?我真的可以在 condition_variable
上同时做 wait
和 wait_for
吗?如果一个线程通过调用 CondVarWrapper::Wait()
获得了 cv_mutex
并且这个线程由于某种原因从未 returned 怎么办。然后另一个线程进入调用 CondVarWrapper::WaitFor(std::chrono::seconds(3))
,如果它在 3 秒内没有成功,则期望 return 退出。现在,第二个线程将无法在 3 秒后从 WaitFor
中 return,不是吗?事实上,它永远不会 return。因为 condition_variable
等待是定时等待而不是 cv_mutex
上的锁。我对这里的理解是正确的还是错误的?
如果我在上面是正确的,那么我需要用 std::timed_mutex cv_mutex
替换 std::mutex cv_mutex
并在 CondVarWrapper::WaitFor
中执行 timed_wait 并在 [=25 上无限等待=]?或者有什么 better/easier 的处理方法吗?
在条件变量 cond_var
上调用 std::condition::wait
时释放互斥锁。因此,当您从一个线程调用 CondVarWrapper::Wait
时,它会在调用 std::condition::wait
时释放互斥量并永远挂在那里,第二个线程仍然可以调用 CondVarWrapper::WaitFor
并成功锁定互斥量 cv_mutex
.
场景:
我有一个基于 condition_variable 的等待和信号机制。这行得通!但我需要的不仅仅是 classic 等待和信号机制。我需要能够进行定时等待和无限等待 "on the same condition_variable
"。因此,我围绕 condition_variable
创建了一个包装器 class,它也处理虚假唤醒问题。以下是相关代码:
代码:
// 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();
}
问题:
上面的代码很好,但我认为有一个问题?我真的可以在 condition_variable
上同时做 wait
和 wait_for
吗?如果一个线程通过调用 CondVarWrapper::Wait()
获得了 cv_mutex
并且这个线程由于某种原因从未 returned 怎么办。然后另一个线程进入调用 CondVarWrapper::WaitFor(std::chrono::seconds(3))
,如果它在 3 秒内没有成功,则期望 return 退出。现在,第二个线程将无法在 3 秒后从 WaitFor
中 return,不是吗?事实上,它永远不会 return。因为 condition_variable
等待是定时等待而不是 cv_mutex
上的锁。我对这里的理解是正确的还是错误的?
如果我在上面是正确的,那么我需要用 std::timed_mutex cv_mutex
替换 std::mutex cv_mutex
并在 CondVarWrapper::WaitFor
中执行 timed_wait 并在 [=25 上无限等待=]?或者有什么 better/easier 的处理方法吗?
在条件变量 cond_var
上调用 std::condition::wait
时释放互斥锁。因此,当您从一个线程调用 CondVarWrapper::Wait
时,它会在调用 std::condition::wait
时释放互斥量并永远挂在那里,第二个线程仍然可以调用 CondVarWrapper::WaitFor
并成功锁定互斥量 cv_mutex
.