在 C++ 中等待事件发生的最佳方法是什么?
What is the best way to to wait until event happen in c++?
我正在使用 fastdds 发布者,按照代码发布数据。
getMatchedStatus() returns publication_matched 回调状态
如果订阅者匹配,getMatchedStatus() = 1
如果没有匹配的订阅者,getMatchedStatus() = 0
如果订阅者在读取数据后关闭,getMatchedStatus() = -1
void publish(){
while (getMatchedStatus() == 0) { **// waiting for a subscriber** what is the best way to replace this sleep?
std::this_thread::sleep_for(std::chrono::milliseconds(250));//250ms
}
while (getMatchedStatus() == 1) {
writer_.write(&Topic);
if (getMatchedStatus() == -1) { // Check subscriber unmatched status
break;
}
}
}
我需要一个合适的或最好的方法来等待匹配的订阅者.....
正在使用 std::this_thread::sleep_for(std::chrono::milliseconds(250));//250ms
好的?生产代码?
第一个 while 循环应该在不让处理器忙碌的情况下等待...
我可以想到三种解决方案:Sleeps、Condition Variables 和 WaitSets。然而,在我看来,使用睡眠似乎是效率较低的一种(但可能是最容易实现的):
正在使用睡眠
作为一般规则:不建议使用休眠来等待事件。通过使用休眠,您失去了对线程的控制,并且您依赖于固定值而不是等待真正的事件。这会使您醒来的次数超过所需次数,并且在需要时不醒来。
但是,如果你的application/library不是real-time导向的,不需要效率,那也是一个选择。
使用 C++ STL
使用 <condition_variable>
下的 class std::condition_variable
将提供简单高效的方式来等待发布匹配,并唤醒任何其他线程。
Fast-DDS 存储库中有一个示例使用此确切方法,以便发布者等待订阅者匹配:https://github.com/eProsima/Fast-DDS/tree/master/examples/C%2B%2B/DDS/BasicConfigurationExample。
解决方案将如下所示:
// Your publish method
void publish(){
// Wait in condition variable till predicate is true
std::unique_lock<std::mutex> lck(wait_matched_cv_mtx_); // Internal DataWriter mutex
wait_matched_cv_.wait(lck, [this] {
return matched(); // Implement matched method in DataWriter or any method similar
});
// At this point it is sure that DataWriter has matched
while (getMatchedStatus() == 1) {
writer_.write(&Topic);
if (getMatchedStatus() == -1) { // Check subscriber unmatched status
break;
}
}
}
// DataWriterListener overrided method (this should be implemented by the listener passed to the DataWriter when created.
void HelloWorldPublisher::PubListener::on_publication_matched(
eprosima::fastdds::dds::DataWriter*,
const eprosima::fastdds::dds::PublicationMatchedStatus& info) {
if (info.current_count_change == 1) {
std::unique_lock<std::mutex> lck(wait_matched_cv_mtx_);
publisher_condition_variable_.notify_all();
}
}
注意:强烈建议在使用条件变量时使用互斥量和谓词。检查以下 post:predicate for condition variable
本机 WaitSets
Fast-DDS 中有一个名为 WaitSets 的最新功能,用于这个确切的提议。这允许等待事件,如收到消息或实体匹配。它实际上做的是包装 std::condition_variable
class 以便它可以与更多含糖方法一起使用。
查看 Fast-DDS 文档以了解如何使用它们:https://fast-dds.docs.eprosima.com/en/latest/fastdds/dds_layer/core/waitsets/waitsets.html .
我正在使用 fastdds 发布者,按照代码发布数据。 getMatchedStatus() returns publication_matched 回调状态
如果订阅者匹配,getMatchedStatus() = 1
如果没有匹配的订阅者,getMatchedStatus() = 0
如果订阅者在读取数据后关闭,getMatchedStatus() = -1
void publish(){
while (getMatchedStatus() == 0) { **// waiting for a subscriber** what is the best way to replace this sleep?
std::this_thread::sleep_for(std::chrono::milliseconds(250));//250ms
}
while (getMatchedStatus() == 1) {
writer_.write(&Topic);
if (getMatchedStatus() == -1) { // Check subscriber unmatched status
break;
}
}
}
我需要一个合适的或最好的方法来等待匹配的订阅者.....
正在使用 std::this_thread::sleep_for(std::chrono::milliseconds(250));//250ms 好的?生产代码?
第一个 while 循环应该在不让处理器忙碌的情况下等待...
我可以想到三种解决方案:Sleeps、Condition Variables 和 WaitSets。然而,在我看来,使用睡眠似乎是效率较低的一种(但可能是最容易实现的):
正在使用睡眠
作为一般规则:不建议使用休眠来等待事件。通过使用休眠,您失去了对线程的控制,并且您依赖于固定值而不是等待真正的事件。这会使您醒来的次数超过所需次数,并且在需要时不醒来。 但是,如果你的application/library不是real-time导向的,不需要效率,那也是一个选择。
使用 C++ STL
使用 <condition_variable>
下的 class std::condition_variable
将提供简单高效的方式来等待发布匹配,并唤醒任何其他线程。
Fast-DDS 存储库中有一个示例使用此确切方法,以便发布者等待订阅者匹配:https://github.com/eProsima/Fast-DDS/tree/master/examples/C%2B%2B/DDS/BasicConfigurationExample。
解决方案将如下所示:
// Your publish method
void publish(){
// Wait in condition variable till predicate is true
std::unique_lock<std::mutex> lck(wait_matched_cv_mtx_); // Internal DataWriter mutex
wait_matched_cv_.wait(lck, [this] {
return matched(); // Implement matched method in DataWriter or any method similar
});
// At this point it is sure that DataWriter has matched
while (getMatchedStatus() == 1) {
writer_.write(&Topic);
if (getMatchedStatus() == -1) { // Check subscriber unmatched status
break;
}
}
}
// DataWriterListener overrided method (this should be implemented by the listener passed to the DataWriter when created.
void HelloWorldPublisher::PubListener::on_publication_matched(
eprosima::fastdds::dds::DataWriter*,
const eprosima::fastdds::dds::PublicationMatchedStatus& info) {
if (info.current_count_change == 1) {
std::unique_lock<std::mutex> lck(wait_matched_cv_mtx_);
publisher_condition_variable_.notify_all();
}
}
注意:强烈建议在使用条件变量时使用互斥量和谓词。检查以下 post:predicate for condition variable
本机 WaitSets
Fast-DDS 中有一个名为 WaitSets 的最新功能,用于这个确切的提议。这允许等待事件,如收到消息或实体匹配。它实际上做的是包装 std::condition_variable
class 以便它可以与更多含糖方法一起使用。
查看 Fast-DDS 文档以了解如何使用它们:https://fast-dds.docs.eprosima.com/en/latest/fastdds/dds_layer/core/waitsets/waitsets.html .