-
Notifications
You must be signed in to change notification settings - Fork 117
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make service wait for response reader #390
Changes from 3 commits
fce9022
f4754e5
3e14a6b
13c540b
3c48b25
118b9a3
2590645
404072b
0fe164a
c13c8af
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,6 +34,7 @@ | |
#include "rmw_fastrtps_shared_cpp/TypeSupport.hpp" | ||
|
||
class ServiceListener; | ||
class ServicePubListener; | ||
|
||
typedef struct CustomServiceInfo | ||
{ | ||
|
@@ -44,6 +45,7 @@ typedef struct CustomServiceInfo | |
eprosima::fastrtps::Subscriber * request_subscriber_; | ||
eprosima::fastrtps::Publisher * response_publisher_; | ||
ServiceListener * listener_; | ||
ServicePubListener * pub_listener_; | ||
eprosima::fastrtps::Participant * participant_; | ||
const char * typesupport_identifier_; | ||
} CustomServiceInfo; | ||
|
@@ -84,6 +86,12 @@ class ServiceListener : public eprosima::fastrtps::SubscriberListener | |
if (sub->takeNextData(&data, &request.sample_info_)) { | ||
if (eprosima::fastrtps::rtps::ALIVE == request.sample_info_.sampleKind) { | ||
request.sample_identity_ = request.sample_info_.sample_identity; | ||
// Use response subscriber guid (on related_sample_identity) when present. | ||
const eprosima::fastrtps::rtps::GUID_t& reader_guid = | ||
request.sample_info_.related_sample_identity.writer_guid(); | ||
if (reader_guid != eprosima::fastrtps::rtps::GUID_t::unknown() ) { | ||
request.sample_identity_.writer_guid() = reader_guid; | ||
} | ||
|
||
std::lock_guard<std::mutex> lock(internalMutex_); | ||
|
||
|
@@ -159,4 +167,45 @@ class ServiceListener : public eprosima::fastrtps::SubscriberListener | |
std::condition_variable * conditionVariable_ RCPPUTILS_TSA_GUARDED_BY(internalMutex_); | ||
}; | ||
|
||
class ServicePubListener : public eprosima::fastrtps::PublisherListener | ||
{ | ||
public: | ||
explicit ServicePubListener() = default; | ||
|
||
template< class Rep, class Period > | ||
bool wait_for_subscription( | ||
const eprosima::fastrtps::rtps::GUID_t & guid, | ||
const std::chrono::duration<Rep, Period> & rel_time) | ||
{ | ||
auto guid_is_present = [this, guid]() -> bool | ||
{ | ||
return subscriptions_.find(guid) != subscriptions_.end(); | ||
}; | ||
|
||
std::unique_lock<std::mutex> lock(mutex_); | ||
return cv_.wait_for(lock, rel_time, guid_is_present); | ||
} | ||
|
||
void onPublicationMatched( | ||
eprosima::fastrtps::Publisher * pub, | ||
eprosima::fastrtps::rtps::MatchingInfo & matchingInfo) | ||
{ | ||
(void) pub; | ||
std::lock_guard<std::mutex> lock(mutex_); | ||
if (eprosima::fastrtps::rtps::MATCHED_MATCHING == matchingInfo.status) { | ||
subscriptions_.insert(matchingInfo.remoteEndpointGuid); | ||
} else if (eprosima::fastrtps::rtps::REMOVED_MATCHING == matchingInfo.status) { | ||
subscriptions_.erase(matchingInfo.remoteEndpointGuid); | ||
} else { | ||
return; | ||
} | ||
cv_.notify_all(); | ||
} | ||
|
||
private: | ||
std::mutex mutex_; | ||
std::set<eprosima::fastrtps::rtps::GUID_t> subscriptions_ RCPPUTILS_TSA_GUARDED_BY(mutex_); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: prefer There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done in 3c48b25. I had to add a hash function for |
||
std::condition_variable cv_; | ||
}; | ||
|
||
#endif // RMW_FASTRTPS_SHARED_CPP__CUSTOM_SERVICE_INFO_HPP_ |
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -104,6 +104,22 @@ __rmw_send_response( | |||||||
wparams.related_sample_identity().sequence_number().low = | ||||||||
(int32_t)(request_header->sequence_number & 0xFFFFFFFF); | ||||||||
|
||||||||
// According to the list of possible entity kinds in section 9.3.1.2 of RTPS | ||||||||
// readers will have this bit on, while writers will not. We use this to know | ||||||||
// if the related guid is the request writer or the response reader. | ||||||||
constexpr uint8_t entity_id_is_reader_bit = 0x04; | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @MiguelCompany mind to add a TODO for a proper fix? I opened an #392 to track that work. |
||||||||
const eprosima::fastrtps::rtps::GUID_t & related_guid = | ||||||||
wparams.related_sample_identity().writer_guid(); | ||||||||
ivanpauno marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
if((related_guid.entityId.value[3] & entity_id_is_reader_bit) != 0) | ||||||||
{ | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this will cause a linter error
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed on 13c540b |
||||||||
// Related guid is a reader, so it is the response subscription guid. | ||||||||
// Wait for the response writer to be matched with it. | ||||||||
if(!info->pub_listener_->wait_for_subscription(related_guid, std::chrono::milliseconds(100))) { | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed on 13c540b There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What if we change this to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Based on the conversation below, I assume the code is ok as it is right now. If this be changed to an indefinite block, please tell me and I'll do it |
||||||||
RMW_SET_ERROR_MSG("client will not receive response"); | ||||||||
return RMW_RET_ERROR; | ||||||||
} | ||||||||
} | ||||||||
|
||||||||
rmw_fastrtps_shared_cpp::SerializedData data; | ||||||||
data.is_cdr_buffer = false; | ||||||||
data.data = const_cast<void *>(ros_response); | ||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the linter doesn't accept that style (it the linter is happy, no change needed).
Suggested style:
if (response.sample_identity_.writer_guid() == info_->reader_guid_ || response.sample_identity_.writer_guid() == info_->writer_guid_) {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed on 13c540b