|
34 | 34 | #include "rclcpp/experimental/action_server_intra_process_base.hpp" |
35 | 35 | #include "rclcpp/experimental/client_intra_process.hpp" |
36 | 36 | #include "rclcpp/experimental/client_intra_process_base.hpp" |
| 37 | +#include "rclcpp/experimental/buffers/intra_process_buffer.hpp" |
37 | 38 | #include "rclcpp/experimental/ros_message_intra_process_buffer.hpp" |
38 | 39 | #include "rclcpp/experimental/service_intra_process.hpp" |
39 | 40 | #include "rclcpp/experimental/service_intra_process_base.hpp" |
@@ -120,9 +121,76 @@ class IntraProcessManager |
120 | 121 | * \param subscription the SubscriptionIntraProcess to register. |
121 | 122 | * \return an unsigned 64-bit integer which is the subscription's unique id. |
122 | 123 | */ |
| 124 | + template< |
| 125 | + typename ROSMessageType, |
| 126 | + typename Alloc = std::allocator<ROSMessageType> |
| 127 | + > |
123 | 128 | RCLCPP_PUBLIC |
124 | 129 | uint64_t |
125 | | - add_subscription(rclcpp::experimental::SubscriptionIntraProcessBase::SharedPtr subscription); |
| 130 | + add_subscription(rclcpp::experimental::SubscriptionIntraProcessBase::SharedPtr subscription) |
| 131 | + { |
| 132 | + using ROSMessageTypeAllocatorTraits = allocator::AllocRebind<ROSMessageType, Alloc>; |
| 133 | + using ROSMessageTypeAllocator = typename ROSMessageTypeAllocatorTraits::allocator_type; |
| 134 | + using ROSMessageTypeDeleter = allocator::Deleter<ROSMessageTypeAllocator, ROSMessageType>; |
| 135 | + |
| 136 | + std::unique_lock<std::shared_timed_mutex> lock(mutex_); |
| 137 | + |
| 138 | + uint64_t sub_id = IntraProcessManager::get_next_unique_id(); |
| 139 | + |
| 140 | + subscriptions_[sub_id] = subscription; |
| 141 | + |
| 142 | + // adds the subscription id to all the matchable publishers |
| 143 | + for (auto & pair : publishers_) { |
| 144 | + auto publisher = pair.second.lock(); |
| 145 | + if (!publisher) { |
| 146 | + continue; |
| 147 | + } |
| 148 | + if (can_communicate(publisher, subscription)) { |
| 149 | + uint64_t pub_id = pair.first; |
| 150 | + insert_sub_id_for_pub(sub_id, pub_id, subscription->use_take_shared_method()); |
| 151 | + if (publisher->is_durability_transient_local() && |
| 152 | + subscription->is_durability_transient_local()) |
| 153 | + { |
| 154 | + auto publisher_buffer = publisher_buffers_[pub_id].lock(); |
| 155 | + if (!publisher_buffer) { |
| 156 | + throw std::runtime_error("publisher buffer has unexpectedly gone out of scope"); |
| 157 | + } |
| 158 | + auto buffer = std::dynamic_pointer_cast< |
| 159 | + rclcpp::experimental::buffers::IntraProcessBuffer< |
| 160 | + ROSMessageType, |
| 161 | + ROSMessageTypeAllocator, |
| 162 | + ROSMessageTypeDeleter |
| 163 | + > |
| 164 | + >(publisher_buffer); |
| 165 | + if (!buffer) { |
| 166 | + throw std::runtime_error( |
| 167 | + "failed to dynamic cast publisher's IntraProcessBufferBase to " |
| 168 | + "IntraProcessBuffer<ROSMessageType,ROSMessageTypeAllocator," |
| 169 | + "ROSMessageTypeDeleter> which can happen when the publisher and " |
| 170 | + "subscription use different allocator types, which is not supported"); |
| 171 | + } |
| 172 | + if (subscription->use_take_shared_method()) { |
| 173 | + auto data_vec = buffer->get_all_data_shared(); |
| 174 | + for (auto shared_data : data_vec) { |
| 175 | + this->template add_shared_msg_to_buffer< |
| 176 | + ROSMessageType, ROSMessageTypeAllocator, ROSMessageTypeDeleter, ROSMessageType>( |
| 177 | + shared_data, sub_id); |
| 178 | + } |
| 179 | + } else { |
| 180 | + auto data_vec = buffer->get_all_data_unique(); |
| 181 | + for (auto & owned_data : data_vec) { |
| 182 | + auto allocator = ROSMessageTypeAllocator(); |
| 183 | + this->template add_owned_msg_to_buffer< |
| 184 | + ROSMessageType, ROSMessageTypeAllocator, ROSMessageTypeDeleter, ROSMessageType>( |
| 185 | + std::move(owned_data), sub_id, allocator); |
| 186 | + } |
| 187 | + } |
| 188 | + } |
| 189 | + } |
| 190 | + } |
| 191 | + |
| 192 | + return sub_id; |
| 193 | + } |
126 | 194 |
|
127 | 195 | /// Register an intra-process client with the manager, returns the client unique id. |
128 | 196 | /** |
@@ -218,7 +286,10 @@ class IntraProcessManager |
218 | 286 | */ |
219 | 287 | RCLCPP_PUBLIC |
220 | 288 | uint64_t |
221 | | - add_publisher(rclcpp::PublisherBase::SharedPtr publisher); |
| 289 | + add_publisher( |
| 290 | + rclcpp::PublisherBase::SharedPtr publisher, |
| 291 | + rclcpp::experimental::buffers::IntraProcessBufferBase::SharedPtr buffer = |
| 292 | + rclcpp::experimental::buffers::IntraProcessBufferBase::SharedPtr()); |
222 | 293 |
|
223 | 294 | /// Unregister a publisher using the publisher's unique id. |
224 | 295 | /** |
@@ -789,6 +860,9 @@ class IntraProcessManager |
789 | 860 | using PublisherMap = |
790 | 861 | std::unordered_map<uint64_t, rclcpp::PublisherBase::WeakPtr>; |
791 | 862 |
|
| 863 | + using PublisherBufferMap = |
| 864 | + std::unordered_map<uint64_t, rclcpp::experimental::buffers::IntraProcessBufferBase::WeakPtr>; |
| 865 | + |
792 | 866 | using PublisherToSubscriptionIdsMap = |
793 | 867 | std::unordered_map<uint64_t, SplittedSubscriptions>; |
794 | 868 |
|
@@ -1023,6 +1097,7 @@ class IntraProcessManager |
1023 | 1097 | ActionClientToServerIdsMap action_clients_to_servers_; |
1024 | 1098 |
|
1025 | 1099 | std::unordered_map<size_t, uint64_t> clients_uuid_to_id_; |
| 1100 | + PublisherBufferMap publisher_buffers_; |
1026 | 1101 |
|
1027 | 1102 | mutable std::shared_timed_mutex mutex_; |
1028 | 1103 | }; |
|
0 commit comments