OSSIA
Open Scenario System for Interactive Application
timer.hpp
1 #pragma once
3 
4 #include <boost/asio/steady_timer.hpp>
5 #include <boost/asio/strand.hpp>
6 #include <boost/asio/use_future.hpp>
7 
8 namespace ossia
9 {
10 
11 class timer
12 {
13 public:
14  explicit timer(boost::asio::io_context& ctx)
15  : m_ctx{&ctx}
16  , m_timer{boost::asio::make_strand(ctx)}
17  {
18  }
19 
20  timer(const timer&) = delete;
21  timer(timer&&) = default;
22  timer& operator=(const timer&) = delete;
23  timer& operator=(timer&&) = default;
24 
25  ~timer() { stop(); }
26 
27  void set_delay(std::chrono::milliseconds ms) noexcept { m_delay = ms; }
28 
29  template <typename F>
30  void start(F f)
31  {
32  m_timer.expires_from_now(m_delay);
33  m_timer.async_wait([this, ff = std::move(f)](auto ec) {
34  if(ec == boost::asio::error::operation_aborted)
35  return;
36  else if(ec)
37  {
38  ossia::logger().error("timer error: {}", ec.message());
39  return;
40  }
41  else
42  {
43  ff();
44  this->start(std::move(ff));
45  }
46  });
47  }
48 
49  void stop()
50  {
51  boost::asio::dispatch(
52  m_timer.get_executor(), [tm = std::make_shared<boost::asio::steady_timer>(
53  std::move(m_timer))]() mutable { tm->cancel(); });
54  std::future<void> wait
55  = boost::asio::dispatch(m_timer.get_executor(), boost::asio::use_future);
56  wait.get();
57  }
58 
59 private:
60  boost::asio::io_context* m_ctx{};
61  boost::asio::steady_timer m_timer;
62  std::chrono::milliseconds m_delay{};
63 };
64 
65 }
Definition: git_info.h:7
spdlog::logger & logger() noexcept
Where the errors will be logged. Default is stderr.
Definition: context.cpp:104