15 #ifndef RCLCPP__EXPERIMENTAL__BUFFERS__RING_BUFFER_IMPLEMENTATION_HPP_
16 #define RCLCPP__EXPERIMENTAL__BUFFERS__RING_BUFFER_IMPLEMENTATION_HPP_
24 #include "rclcpp/experimental/buffers/buffer_implementation_base.hpp"
25 #include "rclcpp/logger.hpp"
26 #include "rclcpp/logging.hpp"
27 #include "rclcpp/macros.hpp"
28 #include "rclcpp/visibility_control.hpp"
29 #include "tracetools/tracetools.h"
33 namespace experimental
42 template<
typename BufferT>
47 : capacity_(capacity),
48 ring_buffer_(capacity),
49 write_index_(capacity_ - 1),
54 throw std::invalid_argument(
"capacity must be a positive, non-zero value");
56 TRACETOOLS_TRACEPOINT(
57 rclcpp_construct_ring_buffer,
58 static_cast<const void *
>(
this),
72 std::lock_guard<std::mutex> lock(mutex_);
74 write_index_ = next_(write_index_);
75 ring_buffer_[write_index_] = std::move(request);
76 TRACETOOLS_TRACEPOINT(
77 rclcpp_ring_buffer_enqueue,
78 static_cast<const void *
>(
this),
84 read_index_ = next_(read_index_);
98 std::lock_guard<std::mutex> lock(mutex_);
104 auto request = std::move(ring_buffer_[read_index_]);
105 TRACETOOLS_TRACEPOINT(
106 rclcpp_ring_buffer_dequeue,
107 static_cast<const void *
>(
this),
110 read_index_ = next_(read_index_);
125 return get_all_data_impl();
137 std::lock_guard<std::mutex> lock(mutex_);
149 std::lock_guard<std::mutex> lock(mutex_);
162 std::lock_guard<std::mutex> lock(mutex_);
174 std::lock_guard<std::mutex> lock(mutex_);
175 return available_capacity_();
178 void clear()
override
180 TRACETOOLS_TRACEPOINT(rclcpp_ring_buffer_clear,
static_cast<const void *
>(
this));
191 inline size_t next_(
size_t val)
193 return (val + 1) % capacity_;
202 inline bool has_data_()
const
214 inline bool is_full_()
const
216 return size_ == capacity_;
225 inline size_t available_capacity_()
const
227 return capacity_ - size_;
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
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
252 std::vector<BufferT> get_all_data_impl()
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 const auto & elem(ring_buffer_[(read_index_ +
id) % capacity_]);
259 if (elem !=
nullptr) {
260 result_vtr.emplace_back(
new typename is_std_unique_ptr<T>::Ptr_type(
263 result_vtr.emplace_back(
nullptr);
269 template<
typename T = BufferT, std::enable_if_t<
270 std::is_copy_constructible<T>::value,
void> * =
nullptr>
271 std::vector<BufferT> get_all_data_impl()
273 std::lock_guard<std::mutex> lock(mutex_);
274 std::vector<BufferT> result_vtr;
275 result_vtr.reserve(size_);
276 for (
size_t id = 0;
id < size_; ++id) {
277 result_vtr.emplace_back(ring_buffer_[(read_index_ +
id) % capacity_]);
282 template<typename T = BufferT, std::enable_if_t<!is_std_unique_ptr<T>::value &&
283 !std::is_copy_constructible<T>::value,
void> * =
nullptr>
284 std::vector<BufferT> get_all_data_impl()
286 throw std::logic_error(
"Underlined type results in invalid get_all_data_impl()");
290 template<typename T = BufferT, std::enable_if_t<is_std_unique_ptr<T>::value &&
291 !std::is_copy_constructible<typename is_std_unique_ptr<T>::Ptr_type>::value,
293 std::vector<BufferT> get_all_data_impl()
295 throw std::logic_error(
"Underlined type in unique_ptr results in invalid get_all_data_impl()");
301 std::vector<BufferT> ring_buffer_;
307 mutable std::mutex mutex_;
Store elements in a fixed-size, FIFO buffer.
bool is_full() const
Get if the size of the buffer is equal to its capacity.
bool has_data() const override
Get if the ring buffer has at least one element stored.
size_t available_capacity() const override
Get the remaining capacity to store messages.
std::vector< BufferT > get_all_data() override
Get all the elements from the ring buffer.
void enqueue(BufferT request) override
Add a new element to store in the ring buffer.
size_t next(size_t val)
Get the next index value for the ring buffer.
BufferT dequeue() override
Remove the oldest element from ring buffer.
Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.