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 
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 
57 
58  void enqueue(BufferT request)
59  {
60  std::lock_guard<std::mutex> lock(mutex_);
61 
62  write_index_ = next(write_index_);
63  ring_buffer_[write_index_] = std::move(request);
64 
65  if (is_full()) {
66  read_index_ = next(read_index_);
67  } else {
68  size_++;
69  }
70  }
71 
72  BufferT dequeue()
73  {
74  std::lock_guard<std::mutex> lock(mutex_);
75 
76  if (!has_data()) {
77  RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Calling dequeue on empty intra-process buffer");
78  throw std::runtime_error("Calling dequeue on empty intra-process buffer");
79  }
80 
81  auto request = std::move(ring_buffer_[read_index_]);
82  read_index_ = next(read_index_);
83 
84  size_--;
85 
86  return request;
87  }
88 
89  inline size_t next(size_t val)
90  {
91  return (val + 1) % capacity_;
92  }
93 
94  inline bool has_data() const
95  {
96  return size_ != 0;
97  }
98 
99  inline bool is_full()
100  {
101  return size_ == capacity_;
102  }
103 
104  void clear() {}
105 
106 private:
107  size_t capacity_;
108 
109  std::vector<BufferT> ring_buffer_;
110 
111  size_t write_index_;
112  size_t read_index_;
113  size_t size_;
114 
115  std::mutex mutex_;
116 };
117 
118 } // namespace buffers
119 } // namespace experimental
120 } // namespace rclcpp
121 
122 #endif // RCLCPP__EXPERIMENTAL__BUFFERS__RING_BUFFER_IMPLEMENTATION_HPP_
bool is_full()
Definition: ring_buffer_implementation.hpp:99
Logger get_logger(const std::string &name)
Return a named logger.
Definition: ring_buffer_implementation.hpp:41
This header provides the get_node_base_interface() template function.
Definition: allocator_common.hpp:24
void clear()
Definition: ring_buffer_implementation.hpp:104
#define RCLCPP_ERROR(logger,...)
Definition: logging.hpp:1418
T move(T... args)
void enqueue(BufferT request)
Definition: ring_buffer_implementation.hpp:58
BufferT dequeue()
Definition: ring_buffer_implementation.hpp:72
bool has_data() const
Definition: ring_buffer_implementation.hpp:94
size_t next(size_t val)
Definition: ring_buffer_implementation.hpp:89
Definition: buffer_implementation_base.hpp:26
RingBufferImplementation(size_t capacity)
Definition: ring_buffer_implementation.hpp:44
virtual ~RingBufferImplementation()
Definition: ring_buffer_implementation.hpp:56