Program Listing for File babel_fish_service_client.hpp
↰ Return to documentation for file (include/ros_babel_fish/detail/babel_fish_service_client.hpp
)
// Copyright (c) 2021 Stefan Fabian. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#ifndef ROS_BABEL_FISH_BABEL_FISH_SERVICE_CLIENT_HPP
#define ROS_BABEL_FISH_BABEL_FISH_SERVICE_CLIENT_HPP
#include <rclcpp/node.hpp>
#include <ros_babel_fish/idl/type_support.hpp>
#include <ros_babel_fish/messages/compound_message.hpp>
namespace ros_babel_fish
{
class BabelFishServiceClient : public rclcpp::ClientBase
{
public:
using SharedRequest = CompoundMessage::SharedPtr;
using SharedResponse = CompoundMessage::SharedPtr;
using Promise = std::promise<SharedResponse>;
using PromiseWithRequest = std::promise<std::pair<SharedRequest, SharedResponse>>;
using SharedPromise = std::shared_ptr<Promise>;
using SharedPromiseWithRequest = std::shared_ptr<PromiseWithRequest>;
using SharedFuture = std::shared_future<SharedResponse>;
using SharedFutureWithRequest = std::shared_future<std::pair<SharedRequest, SharedResponse>>;
using CallbackType = std::function<void( SharedFuture )>;
using CallbackWithRequestType = std::function<void( const SharedFutureWithRequest & )>;
RCLCPP_SMART_PTR_DEFINITIONS( BabelFishServiceClient )
BabelFishServiceClient( rclcpp::node_interfaces::NodeBaseInterface *node_base,
rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph,
const std::string &service_name,
ServiceTypeSupport::ConstSharedPtr type_support,
rcl_client_options_t client_options );
bool take_response( CompoundMessage &response_out, rmw_request_id_t &request_header_out );
std::shared_ptr<void> create_response() override;
std::shared_ptr<rmw_request_id_t> create_request_header() override;
SharedFuture async_send_request( SharedRequest request );
template<typename CallbackT, typename std::enable_if<rclcpp::function_traits::same_arguments<
CallbackT, CallbackType>::value>::type * = nullptr>
SharedFuture async_send_request( const SharedRequest &request, CallbackT &&cb )
{
std::lock_guard<std::mutex> lock( pending_requests_mutex_ );
int64_t sequence_number;
rcl_ret_t ret = rcl_send_request( get_client_handle().get(),
request->type_erased_message().get(), &sequence_number );
if ( RCL_RET_OK != ret ) {
rclcpp::exceptions::throw_from_rcl_error( ret, "failed to send request_template" );
}
SharedPromise call_promise = std::make_shared<Promise>();
SharedFuture f( call_promise->get_future() );
pending_requests_[sequence_number] =
std::make_tuple( call_promise, std::forward<CallbackType>( cb ), f );
return f;
}
template<typename CallbackT, typename std::enable_if<rclcpp::function_traits::same_arguments<
CallbackT, CallbackWithRequestType>::value>::type * = nullptr>
SharedFutureWithRequest async_send_request( SharedRequest request, CallbackT &&cb )
{
SharedPromiseWithRequest promise = std::make_shared<PromiseWithRequest>();
SharedFutureWithRequest future_with_request( promise->get_future() );
auto wrapping_cb = [future_with_request, promise, request, &cb]( const SharedFuture &future ) {
auto response = future.get();
promise->set_value( std::make_pair( request, response ) );
cb( future_with_request );
};
async_send_request( request, wrapping_cb );
return future_with_request;
}
void handle_response( std::shared_ptr<rmw_request_id_t> request_header,
std::shared_ptr<void> response ) override;
private:
RCLCPP_DISABLE_COPY( BabelFishServiceClient )
std::map<int64_t, std::tuple<SharedPromise, CallbackType, SharedFuture>> pending_requests_;
ServiceTypeSupport::ConstSharedPtr type_support_;
std::mutex pending_requests_mutex_;
};
} // namespace ros_babel_fish
#endif // ROS_BABEL_FISH_BABEL_FISH_SERVICE_CLIENT_HPP