rclcpp  master
C++ ROS Client Library API
ring_buffer_implementation.hpp
Go to the documentation of this file.
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 <algorithm>
19 #include <cstddef>
20 #include <cstdint>
21 #include <memory>
22 #include <mutex>
23 #include <stdexcept>
24 #include <utility>
25 #include <vector>
26 
28 #include "rclcpp/logger.hpp"
29 #include "rclcpp/logging.hpp"
30 #include "rclcpp/macros.hpp"
32 
33 namespace rclcpp
34 {
35 namespace experimental
36 {
37 namespace buffers
38 {
39 
41 
44 template<typename BufferT>
46 {
47 public:
48  explicit RingBufferImplementation(size_t capacity)
49  : capacity_(capacity),
50  ring_buffer_(capacity),
51  write_index_(capacity_ - 1),
52  read_index_(0),
53  size_(0)
54  {
55  if (capacity == 0) {
56  throw std::invalid_argument("capacity must be a positive, non-zero value");
57  }
58  }
59 
61 
63 
68  void enqueue(BufferT request)
69  {
70  std::lock_guard<std::mutex> lock(mutex_);
71 
72  write_index_ = next_(write_index_);
73  ring_buffer_[write_index_] = std::move(request);
74 
75  if (is_full_()) {
76  read_index_ = next_(read_index_);
77  } else {
78  size_++;
79  }
80  }
81 
83 
88  BufferT dequeue()
89  {
90  std::lock_guard<std::mutex> lock(mutex_);
91 
92  if (!has_data_()) {
93  RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Calling dequeue on empty intra-process buffer");
94  throw std::runtime_error("Calling dequeue on empty intra-process buffer");
95  }
96 
97  auto request = std::move(ring_buffer_[read_index_]);
98  read_index_ = next_(read_index_);
99 
100  size_--;
101 
102  return request;
103  }
104 
106 
112  inline size_t next(size_t val)
113  {
114  std::lock_guard<std::mutex> lock(mutex_);
115  return next_(val);
116  }
117 
119 
124  inline bool has_data() const
125  {
126  std::lock_guard<std::mutex> lock(mutex_);
127  return has_data_();
128  }
129 
131 
137  inline bool is_full() const
138  {
139  std::lock_guard<std::mutex> lock(mutex_);
140  return is_full_();
141  }
142 
143  void clear() {}
144 
145 private:
147 
153  inline size_t next_(size_t val)
154  {
155  return (val + 1) % capacity_;
156  }
157 
159 
164  inline bool has_data_() const
165  {
166  return size_ != 0;
167  }
168 
170 
176  inline bool is_full_() const
177  {
178  return size_ == capacity_;
179  }
180 
181  size_t capacity_;
182 
183  std::vector<BufferT> ring_buffer_;
184 
185  size_t write_index_;
186  size_t read_index_;
187  size_t size_;
188 
189  mutable std::mutex mutex_;
190 };
191 
192 } // namespace buffers
193 } // namespace experimental
194 } // namespace rclcpp
195 
196 #endif // RCLCPP__EXPERIMENTAL__BUFFERS__RING_BUFFER_IMPLEMENTATION_HPP_
std::move
T move(T... args)
rclcpp::experimental::buffers::RingBufferImplementation::enqueue
void enqueue(BufferT request)
Add a new element to store in the ring buffer.
Definition: ring_buffer_implementation.hpp:68
rclcpp::experimental::buffers::RingBufferImplementation::RingBufferImplementation
RingBufferImplementation(size_t capacity)
Definition: ring_buffer_implementation.hpp:48
rclcpp::experimental::buffers::RingBufferImplementation::has_data
bool has_data() const
Get if the ring buffer has at least one element stored.
Definition: ring_buffer_implementation.hpp:124
std::vector< BufferT >
rclcpp::get_logger
Logger get_logger(const std::string &name)
Return a named logger.
std::lock_guard
rclcpp::experimental::buffers::RingBufferImplementation::dequeue
BufferT dequeue()
Remove the oldest element from ring buffer.
Definition: ring_buffer_implementation.hpp:88
rclcpp::experimental::buffers::RingBufferImplementation::~RingBufferImplementation
virtual ~RingBufferImplementation()
Definition: ring_buffer_implementation.hpp:60
rclcpp::experimental::buffers::RingBufferImplementation
Store elements in a fixed-size, FIFO buffer.
Definition: ring_buffer_implementation.hpp:45
rclcpp::experimental::buffers::RingBufferImplementation::next
size_t next(size_t val)
Get the next index value for the ring buffer.
Definition: ring_buffer_implementation.hpp:112
rclcpp
This header provides the get_node_base_interface() template function.
Definition: allocator_common.hpp:24
buffer_implementation_base.hpp
macros.hpp
rclcpp::experimental::buffers::RingBufferImplementation::is_full
bool is_full() const
Get if the size of the buffer is equal to its capacity.
Definition: ring_buffer_implementation.hpp:137
logging.hpp
rclcpp::experimental::buffers::RingBufferImplementation::clear
void clear()
Definition: ring_buffer_implementation.hpp:143
std::runtime_error
std::invalid_argument
visibility_control.hpp
logger.hpp
std::mutex
rclcpp::experimental::buffers::BufferImplementationBase
Definition: buffer_implementation_base.hpp:26
RCLCPP_ERROR
#define RCLCPP_ERROR(logger,...)
Definition: logging.hpp:1398