ROS 2 rclcpp + rcl - humble  humble
ROS 2 C++ Client Library with ROS Client Library
ring_buffer_implementation.hpp
1 // Copyright 2019 Open Source Robotics Foundation, Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef RCLCPP__EXPERIMENTAL__BUFFERS__RING_BUFFER_IMPLEMENTATION_HPP_
16 #define RCLCPP__EXPERIMENTAL__BUFFERS__RING_BUFFER_IMPLEMENTATION_HPP_
17 
18 #include <mutex>
19 #include <stdexcept>
20 #include <utility>
21 #include <vector>
22 
23 #include "rclcpp/experimental/buffers/buffer_implementation_base.hpp"
24 #include "rclcpp/logger.hpp"
25 #include "rclcpp/logging.hpp"
26 #include "rclcpp/macros.hpp"
27 #include "rclcpp/visibility_control.hpp"
28 
29 namespace rclcpp
30 {
31 namespace experimental
32 {
33 namespace buffers
34 {
35 
37 
40 template<typename BufferT>
42 {
43 public:
44  explicit RingBufferImplementation(size_t capacity)
45  : capacity_(capacity),
46  ring_buffer_(capacity),
47  write_index_(capacity_ - 1),
48  read_index_(0),
49  size_(0)
50  {
51  if (capacity == 0) {
52  throw std::invalid_argument("capacity must be a positive, non-zero value");
53  }
54  }
55 
56  virtual ~RingBufferImplementation() {}
57 
59 
64  void enqueue(BufferT request)
65  {
66  std::lock_guard<std::mutex> lock(mutex_);
67 
68  write_index_ = next_(write_index_);
69  ring_buffer_[write_index_] = std::move(request);
70 
71  if (is_full_()) {
72  read_index_ = next_(read_index_);
73  } else {
74  size_++;
75  }
76  }
77 
79 
84  BufferT dequeue()
85  {
86  std::lock_guard<std::mutex> lock(mutex_);
87 
88  if (!has_data_()) {
89  return BufferT();
90  }
91 
92  auto request = std::move(ring_buffer_[read_index_]);
93  read_index_ = next_(read_index_);
94 
95  size_--;
96 
97  return request;
98  }
99 
101 
107  inline size_t next(size_t val)
108  {
109  std::lock_guard<std::mutex> lock(mutex_);
110  return next_(val);
111  }
112 
114 
119  inline bool has_data() const
120  {
121  std::lock_guard<std::mutex> lock(mutex_);
122  return has_data_();
123  }
124 
126 
132  inline bool is_full() const
133  {
134  std::lock_guard<std::mutex> lock(mutex_);
135  return is_full_();
136  }
137 
138  void clear() {}
139 
140 private:
142 
148  inline size_t next_(size_t val)
149  {
150  return (val + 1) % capacity_;
151  }
152 
154 
159  inline bool has_data_() const
160  {
161  return size_ != 0;
162  }
163 
165 
171  inline bool is_full_() const
172  {
173  return size_ == capacity_;
174  }
175 
176  size_t capacity_;
177 
178  std::vector<BufferT> ring_buffer_;
179 
180  size_t write_index_;
181  size_t read_index_;
182  size_t size_;
183 
184  mutable std::mutex mutex_;
185 };
186 
187 } // namespace buffers
188 } // namespace experimental
189 } // namespace rclcpp
190 
191 #endif // RCLCPP__EXPERIMENTAL__BUFFERS__RING_BUFFER_IMPLEMENTATION_HPP_
bool has_data() const
Get if the ring buffer has at least one element stored.
bool is_full() const
Get if the size of the buffer is equal to its capacity.
BufferT dequeue()
Remove the oldest element from ring buffer.
size_t next(size_t val)
Get the next index value for the ring buffer.
void enqueue(BufferT request)
Add a new element to store in the ring buffer.
Versions of rosidl_typesupport_cpp::get_message_type_support_handle that handle adapted types.