0

I am using fastdds publisher, following code to publish data. getMatchedStatus() returns publication_matched callback status

if subscriber is matched, getMatchedStatus() = 1

if no matching subscriber, getMatchedStatus() = 0

if subscriber shutdown after reading data, 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;
        }
    } 
}

I need a proper way or best way to wait for a matching subscriber.....

is using std::this_thread::sleep_for(std::chrono::milliseconds(250));//250ms okay? for prodcution code?

the 1st while loop should wait without making the processor busy as well...

kingmihi
  • 47
  • 1
  • 8
  • In pure C++ I'd use [`std::condition_variable`](https://en.cppreference.com/w/cpp/thread/condition_variable), but maybe this library provides something else to be used. – Yksisarvinen Jul 06 '21 at 08:04
  • Busy polling is worst and adding sleeps does make it bad in other way (allowing "alive" deadlocks and reducing responsiveness). The way to go are condition variables for single resource or semaphores for shared resource. – Öö Tiib Jul 06 '21 at 10:13
  • @Öö Tiib can show an example of how to use conditional variable here in my code? – kingmihi Jul 07 '21 at 15:51

1 Answers1

1

I can think of three solutions: Sleeps, Condition Variables, and WaitSets. Using sleeps, however, seems to me like the less efficient one (but probably the easiest to implement):

Using sleep

As a general rule: it is not advisable to use sleeps to wait events. By using sleeps, you lose the control on your thread, and you depend on a fixed value rather than waiting for a real event. This makes you awake more times than required, and do not awake when needed. However, if your application/library is not real-time oriented and does not require efficiency, it is always an option.

Using C++ STL

Using the class std::condition_variable under <condition_variable> will provide and easy and efficient way to wait on a publication match, and awake any other thread. There is an example in Fast-DDS repository that uses this exact method in order for the publisher to wait until a subscriber is matched: https://github.com/eProsima/Fast-DDS/tree/master/examples/C%2B%2B/DDS/BasicConfigurationExample . The solution will look like this:

// 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();
    }
}

NOTE: it is strongly recommended to use mutex and predicates when using condition variables. Check following post: predicate for condition variable

Native WaitSets

There is a recent feature in Fast-DDS called WaitSets that are used for this exact propose. This allows to wait for an event, as a message received or an entity match. What it actually does is wrap the std::condition_variable class so it could be used with more sugary methods. Check Fast-DDS documentation in order to learn how to use them: https://fast-dds.docs.eprosima.com/en/latest/fastdds/dds_layer/core/waitsets/waitsets.html .

jparisu
  • 79
  • 6