Program Listing for File agnocast_timer.hpp

Return to documentation for file (include/agnocast/agnocast_timer.hpp)

#pragma once

#include "agnocast/agnocast_public_api.hpp"
#include "rclcpp/clock.hpp"
#include "rclcpp/macros.hpp"

#include <atomic>
#include <chrono>
#include <functional>
#include <memory>
#include <stdexcept>
#include <type_traits>

namespace agnocast
{

struct TimerInfo;

AGNOCAST_PUBLIC
class TimerBase
{
public:
  RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(TimerBase)

  virtual ~TimerBase();

  AGNOCAST_PUBLIC
  void cancel() { canceled_.store(true); }

  // Non-const to align with rclcpp::TimerBase::is_canceled().
  AGNOCAST_PUBLIC
  bool is_canceled() { return canceled_.load(); }

  AGNOCAST_PUBLIC
  void reset();

  AGNOCAST_PUBLIC
  std::chrono::nanoseconds time_until_trigger();

  void set_timer_info(std::weak_ptr<TimerInfo> timer_info) { timer_info_ = timer_info; }

  void set_period(std::chrono::nanoseconds period);

  AGNOCAST_PUBLIC
  virtual bool is_steady() const = 0;

  AGNOCAST_PUBLIC
  virtual rclcpp::Clock::SharedPtr get_clock() const = 0;

  virtual void execute_callback() = 0;

protected:
  TimerBase(uint32_t timer_id, [[maybe_unused]] std::chrono::nanoseconds period)
  : timer_id_(timer_id), timer_info_(), canceled_(false)
  {
  }

  uint32_t timer_id_;
  std::weak_ptr<TimerInfo> timer_info_;
  std::atomic<bool> canceled_;
};

AGNOCAST_PUBLIC
template <typename FunctorT>
class GenericTimer : public TimerBase
{
public:
  RCLCPP_SMART_PTR_DEFINITIONS(GenericTimer)

  GenericTimer(
    uint32_t timer_id, std::chrono::nanoseconds period, rclcpp::Clock::SharedPtr clock,
    FunctorT && callback)
  : TimerBase(timer_id, period),
    clock_(std::move(clock)),
    callback_(std::forward<FunctorT>(callback))
  {
    if (!clock_) {
      throw std::invalid_argument("clock cannot be null");
    }
  }

  void execute_callback() override
  {
    if constexpr (std::is_invocable_v<FunctorT, TimerBase &>) {
      callback_(*this);
    } else {
      callback_();
    }
  }

  AGNOCAST_PUBLIC
  bool is_steady() const override { return clock_->get_clock_type() == RCL_STEADY_TIME; }

  AGNOCAST_PUBLIC
  rclcpp::Clock::SharedPtr get_clock() const override { return clock_; }

protected:
  RCLCPP_DISABLE_COPY(GenericTimer)

  rclcpp::Clock::SharedPtr clock_;
  FunctorT callback_;
};

AGNOCAST_PUBLIC
template <typename FunctorT>
class WallTimer : public GenericTimer<FunctorT>
{
public:
  RCLCPP_SMART_PTR_DEFINITIONS(WallTimer)

  WallTimer(uint32_t timer_id, std::chrono::nanoseconds period, FunctorT && callback)
  : GenericTimer<FunctorT>(
      timer_id, period, std::make_shared<rclcpp::Clock>(RCL_STEADY_TIME),
      std::forward<FunctorT>(callback))
  {
  }

protected:
  RCLCPP_DISABLE_COPY(WallTimer)
};

}  // namespace agnocast