37#ifndef REALTIME_TOOLS__REALTIME_PUBLISHER_HPP_
38#define REALTIME_TOOLS__REALTIME_PUBLISHER_HPP_
42#include <condition_variable>
48#include "rclcpp/publisher.hpp"
52template <
class MessageT>
58 using PublisherSharedPtr =
typename rclcpp::Publisher<MessageT>::SharedPtr;
60 using PublishedType =
typename rclcpp::TypeAdapter<MessageT>::custom_type;
61 using ROSMessageType =
typename rclcpp::TypeAdapter<MessageT>::ros_message_type;
73 : publisher_(publisher), is_running_(false), keep_running_(true), turn_(State::LOOP_NOT_STARTED)
75 thread_ = std::thread(&RealtimePublisher::publishingLoop,
this);
79 "Use constructor with rclcpp::Publisher<T>::SharedPtr instead - this class does not make sense "
80 "without a real publisher")]]
82 : is_running_(false), keep_running_(false), turn_(State::LOOP_NOT_STARTED)
90 while (is_running()) {
91 std::this_thread::sleep_for(std::chrono::microseconds(100));
93 if (thread_.joinable()) {
101 keep_running_ =
false;
102 updated_cond_.notify_one();
113 if (turn_.load(std::memory_order_acquire) == State::NON_REALTIME && msg_mutex_.try_lock()) {
145 turn_.store(State::REALTIME, std::memory_order_release);
155 void lock() { msg_mutex_.lock(); }
163 updated_cond_.notify_one();
166 std::thread & get_thread() {
return thread_; }
168 const std::thread & get_thread()
const {
return thread_; }
175 bool is_running()
const {
return is_running_; }
177 void publishingLoop()
180 turn_.store(State::NON_REALTIME, std::memory_order_release);
182 while (keep_running_) {
187 std::unique_lock<std::mutex> lock_(msg_mutex_);
188 updated_cond_.wait(lock_, [&] {
return turn_ == State::REALTIME || !keep_running_; });
194 publisher_->publish(outgoing);
196 turn_.store(State::NON_REALTIME, std::memory_order_release);
201 PublisherSharedPtr publisher_;
202 std::atomic<bool> is_running_;
203 std::atomic<bool> keep_running_;
207 std::mutex msg_mutex_;
208 std::condition_variable updated_cond_;
210 enum class State :
int { REALTIME, NON_REALTIME, LOOP_NOT_STARTED };
211 std::atomic<State> turn_;
214template <
class MessageT>
215using RealtimePublisherSharedPtr = std::shared_ptr<RealtimePublisher<MessageT>>;