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