scheduler.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013-2023 Regents of the University of California.
4  *
5  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6  *
7  * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8  * terms of the GNU Lesser General Public License as published by the Free Software
9  * Foundation, either version 3 of the License, or (at your option) any later version.
10  *
11  * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13  * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14  *
15  * You should have received copies of the GNU General Public License and GNU Lesser
16  * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17  * <http://www.gnu.org/licenses/>.
18  *
19  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20  */
21 
23 #include "ndn-cxx/util/impl/steady-timer.hpp"
24 #include "ndn-cxx/util/scope.hpp"
25 
26 namespace ndn::scheduler {
27 
31 struct EventInfo : noncopyable
32 {
33  EventInfo(time::nanoseconds after, EventCallback&& cb)
34  : expiry(time::steady_clock::now() + after)
35  , callback(std::move(cb))
36  {
37  }
38 
40  EventCallback callback;
41  Scheduler::EventQueue::const_iterator queueIt;
42  bool isExpired = false;
43 };
44 
45 EventId::EventId(Scheduler& sched, weak_ptr<EventInfo> info)
46  : CancelHandle([&sched, info] { sched.cancelImpl(info.lock()); })
47  , m_info(std::move(info))
48 {
49 }
50 
51 EventId::operator bool() const noexcept
52 {
53  auto sp = m_info.lock();
54  return sp != nullptr && !sp->isExpired;
55 }
56 
57 void
58 EventId::reset() noexcept
59 {
60  *this = {};
61 }
62 
63 bool
64 Scheduler::EventQueueCompare::operator()(const shared_ptr<EventInfo>& a,
65  const shared_ptr<EventInfo>& b) const noexcept
66 {
67  return a->expiry < b->expiry;
68 }
69 
70 Scheduler::Scheduler(boost::asio::io_context& ioCtx)
71  : m_timer(make_unique<detail::SteadyTimer>(ioCtx))
72 {
73 }
74 
75 Scheduler::~Scheduler() = default;
76 
77 EventId
79 {
80  BOOST_ASSERT(callback != nullptr);
81 
82  auto i = m_queue.insert(std::make_shared<EventInfo>(after, std::move(callback)));
83  (*i)->queueIt = i;
84 
85  if (!m_isEventExecuting && i == m_queue.begin()) {
86  // the new event is the first one to expire
87  scheduleNext();
88  }
89 
90  return EventId(*this, *i);
91 }
92 
93 void
94 Scheduler::cancelImpl(const shared_ptr<EventInfo>& info)
95 {
96  if (info == nullptr || info->isExpired) {
97  return;
98  }
99 
100  if (info->queueIt == m_queue.begin()) {
101  m_timer->cancel();
102  }
103  m_queue.erase(info->queueIt);
104 
105  if (!m_isEventExecuting) {
106  scheduleNext();
107  }
108 }
109 
110 void
112 {
113  m_queue.clear();
114  m_timer->cancel();
115 }
116 
117 void
118 Scheduler::scheduleNext()
119 {
120  if (!m_queue.empty()) {
121  m_timer->expires_at((*m_queue.begin())->expiry);
122  m_timer->async_wait([this] (const auto& error) { executeEvent(error); });
123  }
124 }
125 
126 void
127 Scheduler::executeEvent(const boost::system::error_code& error)
128 {
129  if (error) { // e.g., cancelled
130  return;
131  }
132 
133  auto guard = make_scope_exit([this] {
134  m_isEventExecuting = false;
135  scheduleNext();
136  });
137  m_isEventExecuting = true;
138 
139  // process all expired events
140  auto now = time::steady_clock::now();
141  while (!m_queue.empty()) {
142  auto head = m_queue.begin();
143  shared_ptr<EventInfo> info = *head;
144  if (info->expiry > now) {
145  break;
146  }
147 
148  m_queue.erase(head);
149  info->isExpired = true;
150  info->callback();
151  }
152 }
153 
154 } // namespace ndn::scheduler
A handle for a scheduled event.
Definition: scheduler.hpp:62
void reset() noexcept
Clear this EventId without canceling the associated event.
Definition: scheduler.cpp:58
EventId() noexcept=default
Constructs an empty EventId.
Generic time-based event scheduler.
Definition: scheduler.hpp:138
void cancelAllEvents()
Cancel all scheduled events.
Definition: scheduler.cpp:111
Scheduler(boost::asio::io_context &ioCtx)
Definition: scheduler.cpp:70
EventId schedule(time::nanoseconds after, EventCallback callback)
Schedule a one-time event after the specified delay.
Definition: scheduler.cpp:78
static time_point now() noexcept
Definition: time.cpp:79
::boost::chrono::time_point< steady_clock > time_point
Definition: time.hpp:232
std::function< void()> EventCallback
Function to be invoked when a scheduled event expires.
Definition: scheduler.hpp:48
::boost::chrono::nanoseconds nanoseconds
Definition: time.hpp:54
SignatureInfo info