Skip to content

Commit 7901bb9

Browse files
authored
Add transient local durability support to publisher and subscriptions when using intra-process communication (#2303)
* Add intra process transient local durability support to publisher and subscription Signed-off-by: Jeffery Hsu <[email protected]> * Remove durability_is_transient_local_ from publisher_base Signed-off-by: Jeffery Hsu <[email protected]> * Design changes that move most transient local publish functionalities out of intra process manager into intra process manager Signed-off-by: Jeffery Hsu <[email protected]> * Move transient local publish to a separate function Signed-off-by: Jeffery Hsu <[email protected]> * Remove publisher buffer weak ptr from intra process manager when it associated publisher is removed. Signed-off-by: Jeffery Hsu <[email protected]> * Remove incorrectly placed RCLCPP_PUBLIC Signed-off-by: Jeffery Hsu <[email protected]> * Add missing RCLCPP_PUBLIC Signed-off-by: Jeffery Hsu <[email protected]> * Expand RingBufferImplementation beyond shared_ptr and unique_ptr Signed-off-by: Jeffery Hsu <[email protected]> * Comment and format fix Signed-off-by: Jeffery Hsu <[email protected]> --------- Signed-off-by: Jeffery Hsu <[email protected]>
1 parent 6f6b5f2 commit 7901bb9

20 files changed

+921
-211
lines changed

rclcpp/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ set(${PROJECT_NAME}_SRCS
4646
src/rclcpp/context.cpp
4747
src/rclcpp/contexts/default_context.cpp
4848
src/rclcpp/detail/add_guard_condition_to_rcl_wait_set.cpp
49+
src/rclcpp/detail/resolve_intra_process_buffer_type.cpp
4950
src/rclcpp/detail/resolve_parameter_overrides.cpp
5051
src/rclcpp/detail/rmw_implementation_specific_payload.cpp
5152
src/rclcpp/detail/rmw_implementation_specific_publisher_payload.cpp

rclcpp/include/rclcpp/detail/resolve_intra_process_buffer_type.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ resolve_intra_process_buffer_type(
4747
return resolved_buffer_type;
4848
}
4949

50+
RCLCPP_PUBLIC
51+
rclcpp::IntraProcessBufferType
52+
resolve_intra_process_buffer_type(
53+
const rclcpp::IntraProcessBufferType buffer_type);
54+
5055
} // namespace detail
5156

5257
} // namespace rclcpp

rclcpp/include/rclcpp/experimental/buffers/buffer_implementation_base.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#ifndef RCLCPP__EXPERIMENTAL__BUFFERS__BUFFER_IMPLEMENTATION_BASE_HPP_
1616
#define RCLCPP__EXPERIMENTAL__BUFFERS__BUFFER_IMPLEMENTATION_BASE_HPP_
1717

18+
#include <vector>
19+
1820
namespace rclcpp
1921
{
2022
namespace experimental
@@ -31,6 +33,8 @@ class BufferImplementationBase
3133
virtual BufferT dequeue() = 0;
3234
virtual void enqueue(BufferT request) = 0;
3335

36+
virtual std::vector<BufferT> get_all_data() = 0;
37+
3438
virtual void clear() = 0;
3539
virtual bool has_data() const = 0;
3640
virtual size_t available_capacity() const = 0;

rclcpp/include/rclcpp/experimental/buffers/intra_process_buffer.hpp

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <stdexcept>
2020
#include <type_traits>
2121
#include <utility>
22+
#include <vector>
2223

2324
#include "rclcpp/allocator/allocator_common.hpp"
2425
#include "rclcpp/allocator/allocator_deleter.hpp"
@@ -66,6 +67,9 @@ class IntraProcessBuffer : public IntraProcessBufferBase
6667

6768
virtual MessageSharedPtr consume_shared() = 0;
6869
virtual MessageUniquePtr consume_unique() = 0;
70+
71+
virtual std::vector<MessageSharedPtr> get_all_data_shared() = 0;
72+
virtual std::vector<MessageUniquePtr> get_all_data_unique() = 0;
6973
};
7074

7175
template<
@@ -129,6 +133,16 @@ class TypedIntraProcessBuffer : public IntraProcessBuffer<MessageT, Alloc, Messa
129133
return consume_unique_impl<BufferT>();
130134
}
131135

136+
std::vector<MessageSharedPtr> get_all_data_shared() override
137+
{
138+
return get_all_data_shared_impl();
139+
}
140+
141+
std::vector<MessageUniquePtr> get_all_data_unique() override
142+
{
143+
return get_all_data_unique_impl();
144+
}
145+
132146
bool has_data() const override
133147
{
134148
return buffer_->has_data();
@@ -243,6 +257,71 @@ class TypedIntraProcessBuffer : public IntraProcessBuffer<MessageT, Alloc, Messa
243257
{
244258
return buffer_->dequeue();
245259
}
260+
261+
// MessageSharedPtr to MessageSharedPtr
262+
template<typename T = BufferT>
263+
typename std::enable_if<
264+
std::is_same<T, MessageSharedPtr>::value,
265+
std::vector<MessageSharedPtr>
266+
>::type
267+
get_all_data_shared_impl()
268+
{
269+
return buffer_->get_all_data();
270+
}
271+
272+
// MessageUniquePtr to MessageSharedPtr
273+
template<typename T = BufferT>
274+
typename std::enable_if<
275+
std::is_same<T, MessageUniquePtr>::value,
276+
std::vector<MessageSharedPtr>
277+
>::type
278+
get_all_data_shared_impl()
279+
{
280+
std::vector<MessageSharedPtr> result;
281+
auto uni_ptr_vec = buffer_->get_all_data();
282+
result.reserve(uni_ptr_vec.size());
283+
for (MessageUniquePtr & uni_ptr : uni_ptr_vec) {
284+
result.emplace_back(std::move(uni_ptr));
285+
}
286+
return result;
287+
}
288+
289+
// MessageSharedPtr to MessageUniquePtr
290+
template<typename T = BufferT>
291+
typename std::enable_if<
292+
std::is_same<T, MessageSharedPtr>::value,
293+
std::vector<MessageUniquePtr>
294+
>::type
295+
get_all_data_unique_impl()
296+
{
297+
std::vector<MessageUniquePtr> result;
298+
auto shared_ptr_vec = buffer_->get_all_data();
299+
result.reserve(shared_ptr_vec.size());
300+
for (MessageSharedPtr shared_msg : shared_ptr_vec) {
301+
MessageUniquePtr unique_msg;
302+
MessageDeleter * deleter = std::get_deleter<MessageDeleter, const MessageT>(shared_msg);
303+
auto ptr = MessageAllocTraits::allocate(*message_allocator_.get(), 1);
304+
MessageAllocTraits::construct(*message_allocator_.get(), ptr, *shared_msg);
305+
if (deleter) {
306+
unique_msg = MessageUniquePtr(ptr, *deleter);
307+
} else {
308+
unique_msg = MessageUniquePtr(ptr);
309+
}
310+
result.push_back(std::move(unique_msg));
311+
}
312+
return result;
313+
}
314+
315+
// MessageUniquePtr to MessageUniquePtr
316+
template<typename T = BufferT>
317+
typename std::enable_if<
318+
std::is_same<T, MessageUniquePtr>::value,
319+
std::vector<MessageUniquePtr>
320+
>::type
321+
get_all_data_unique_impl()
322+
{
323+
return buffer_->get_all_data();
324+
}
246325
};
247326

248327
} // namespace buffers

rclcpp/include/rclcpp/experimental/buffers/ring_buffer_implementation.hpp

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#ifndef RCLCPP__EXPERIMENTAL__BUFFERS__RING_BUFFER_IMPLEMENTATION_HPP_
1616
#define RCLCPP__EXPERIMENTAL__BUFFERS__RING_BUFFER_IMPLEMENTATION_HPP_
1717

18+
#include <memory>
1819
#include <mutex>
1920
#include <stdexcept>
2021
#include <utility>
@@ -113,6 +114,17 @@ class RingBufferImplementation : public BufferImplementationBase<BufferT>
113114
return request;
114115
}
115116

117+
/// Get all the elements from the ring buffer
118+
/**
119+
* This member function is thread-safe.
120+
*
121+
* \return a vector containing all the elements from the ring buffer
122+
*/
123+
std::vector<BufferT> get_all_data() override
124+
{
125+
return get_all_data_impl();
126+
}
127+
116128
/// Get the next index value for the ring buffer
117129
/**
118130
* This member function is thread-safe.
@@ -215,6 +227,71 @@ class RingBufferImplementation : public BufferImplementationBase<BufferT>
215227
return capacity_ - size_;
216228
}
217229

230+
/// Traits for checking if a type is std::unique_ptr
231+
template<typename ...>
232+
struct is_std_unique_ptr final : std::false_type {};
233+
template<class T, typename ... Args>
234+
struct is_std_unique_ptr<std::unique_ptr<T, Args...>> final : std::true_type
235+
{
236+
typedef T Ptr_type;
237+
};
238+
239+
/// Get all the elements from the ring buffer
240+
/**
241+
* This member function is thread-safe.
242+
* Two versions for the implementation of the function.
243+
* One for buffer containing unique_ptr and the other for other types
244+
*
245+
* \return a vector containing all the elements from the ring buffer
246+
*/
247+
template<typename T = BufferT, std::enable_if_t<is_std_unique_ptr<T>::value &&
248+
std::is_copy_constructible<
249+
typename is_std_unique_ptr<T>::Ptr_type
250+
>::value,
251+
void> * = nullptr>
252+
std::vector<BufferT> get_all_data_impl()
253+
{
254+
std::lock_guard<std::mutex> lock(mutex_);
255+
std::vector<BufferT> result_vtr;
256+
result_vtr.reserve(size_);
257+
for (size_t id = 0; id < size_; ++id) {
258+
result_vtr.emplace_back(
259+
new typename is_std_unique_ptr<T>::Ptr_type(
260+
*(ring_buffer_[(read_index_ + id) % capacity_])));
261+
}
262+
return result_vtr;
263+
}
264+
265+
template<typename T = BufferT, std::enable_if_t<
266+
std::is_copy_constructible<T>::value, void> * = nullptr>
267+
std::vector<BufferT> get_all_data_impl()
268+
{
269+
std::lock_guard<std::mutex> lock(mutex_);
270+
std::vector<BufferT> result_vtr;
271+
result_vtr.reserve(size_);
272+
for (size_t id = 0; id < size_; ++id) {
273+
result_vtr.emplace_back(ring_buffer_[(read_index_ + id) % capacity_]);
274+
}
275+
return result_vtr;
276+
}
277+
278+
template<typename T = BufferT, std::enable_if_t<!is_std_unique_ptr<T>::value &&
279+
!std::is_copy_constructible<T>::value, void> * = nullptr>
280+
std::vector<BufferT> get_all_data_impl()
281+
{
282+
throw std::logic_error("Underlined type results in invalid get_all_data_impl()");
283+
return {};
284+
}
285+
286+
template<typename T = BufferT, std::enable_if_t<is_std_unique_ptr<T>::value &&
287+
!std::is_copy_constructible<typename is_std_unique_ptr<T>::Ptr_type>::value,
288+
void> * = nullptr>
289+
std::vector<BufferT> get_all_data_impl()
290+
{
291+
throw std::logic_error("Underlined type in unique_ptr results in invalid get_all_data_impl()");
292+
return {};
293+
}
294+
218295
size_t capacity_;
219296

220297
std::vector<BufferT> ring_buffer_;

0 commit comments

Comments
 (0)