ros2_control - humble
realtime_buffer.h
1 // Copyright (c) 2013, hiDOF, Inc.
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 //
9 // * Redistributions in binary form must reproduce the above copyright
10 // notice, this list of conditions and the following disclaimer in the
11 // documentation and/or other materials provided with the distribution.
12 //
13 // * Neither the name of the hiDOF, Inc. nor the names of its
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 // POSSIBILITY OF SUCH DAMAGE.
28 
29 /*
30  * Publishing ROS messages is difficult, as the publish function is
31  * not realtime safe. This class provides the proper locking so that
32  * you can call publish in realtime and a separate (non-realtime)
33  * thread will ensure that the message gets published over ROS.
34  *
35  * Author: Wim Meeussen
36  */
37 
38 #ifndef REALTIME_TOOLS__REALTIME_BUFFER_H_
39 #define REALTIME_TOOLS__REALTIME_BUFFER_H_
40 
41 #include <chrono>
42 #include <mutex>
43 #include <thread>
44 
45 namespace realtime_tools
46 {
47 template <class T>
49 {
50 public:
51  RealtimeBuffer() : new_data_available_(false)
52  {
53  // allocate memory
54  non_realtime_data_ = new T();
55  realtime_data_ = new T();
56  }
57 
63  explicit RealtimeBuffer(const T & data) : new_data_available_(false)
64  {
65  // allocate memory
66  non_realtime_data_ = new T(data);
67  realtime_data_ = new T(data);
68  }
69 
71  {
72  if (non_realtime_data_) {
73  delete non_realtime_data_;
74  }
75  if (realtime_data_) {
76  delete realtime_data_;
77  }
78  }
79 
80  RealtimeBuffer(const RealtimeBuffer & source)
81  {
82  // allocate memory
83  non_realtime_data_ = new T();
84  realtime_data_ = new T();
85 
86  // Copy the data from old RTB to new RTB
87  writeFromNonRT(*source.readFromNonRT());
88  }
89 
94  {
95  if (this == &source) {
96  return *this;
97  }
98 
99  // Copy the data from old RTB to new RTB
100  writeFromNonRT(*source.readFromNonRT());
101 
102  return *this;
103  }
104 
105  T * readFromRT()
106  {
107  // Check if the data is currently being written to (is locked)
108  std::unique_lock<std::mutex> guard(mutex_, std::try_to_lock);
109  if (guard.owns_lock()) {
110  // swap pointers
111  if (new_data_available_) {
112  T * tmp = realtime_data_;
113  realtime_data_ = non_realtime_data_;
114  non_realtime_data_ = tmp;
115  new_data_available_ = false;
116  }
117  }
118  return realtime_data_;
119  }
120 
121  T * readFromNonRT() const
122  {
123  std::lock_guard<std::mutex> guard(mutex_);
124 
125  if (new_data_available_) {
126  return non_realtime_data_;
127  } else {
128  return realtime_data_;
129  }
130  }
131 
132  void writeFromNonRT(const T & data)
133  {
134 #ifdef NON_POLLING
135  std::lock_guard<std::mutex> guard(mutex_);
136 #else
137  std::unique_lock<std::mutex> guard(mutex_, std::defer_lock);
138  while (!guard.try_lock()) {
139  std::this_thread::sleep_for(std::chrono::microseconds(500));
140  }
141 #endif
142 
143  // copy data into non-realtime buffer
144  *non_realtime_data_ = data;
145  new_data_available_ = true;
146  }
147 
148  void initRT(const T & data)
149  {
150  *non_realtime_data_ = data;
151  *realtime_data_ = data;
152  }
153 
154  void reset()
155  {
156  // delete the old memory
157  if (non_realtime_data_) {
158  delete non_realtime_data_;
159  }
160  if (realtime_data_) {
161  delete realtime_data_;
162  }
163 
164  // allocate memory
165  non_realtime_data_ = new T();
166  realtime_data_ = new T();
167  }
168 
169 private:
170  T * realtime_data_;
171  T * non_realtime_data_;
172  bool new_data_available_;
173 
174  // Set as mutable so that readFromNonRT() can be performed on a const buffer
175  mutable std::mutex mutex_;
176 }; // class
177 
178 } // namespace realtime_tools
179 #endif // REALTIME_TOOLS__REALTIME_BUFFER_H_
Definition: realtime_buffer.h:49
RealtimeBuffer & operator=(const RealtimeBuffer &source)
Custom assignment operator.
Definition: realtime_buffer.h:93
RealtimeBuffer(const T &data)
Constructor for objects that don't have a default constructor.
Definition: realtime_buffer.h:63
Definition: async_function_handler.hpp:38