blob: 239353505debb8c8d96e250153fe661b2ef98792 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shi5bcab562017-07-16 17:19:14 +00002/*
Alexander Afanasyeve6835fe2017-01-19 20:05:01 -08003 * Copyright (c) 2013-2017 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * 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.
Alexander Afanasyevf6468892014-01-29 01:04:14 -080020 */
21
22#ifndef NDN_UTIL_SCHEDULER_HPP
23#define NDN_UTIL_SCHEDULER_HPP
24
Junxiao Shi5bcab562017-07-16 17:19:14 +000025#include "time.hpp"
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070026#include <set>
Junxiao Shi5bcab562017-07-16 17:19:14 +000027#include <boost/asio/io_service.hpp>
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070028
Alexander Afanasyevf6468892014-01-29 01:04:14 -080029namespace ndn {
Alexander Afanasyev9a9952f2015-01-28 19:06:48 -080030namespace util {
Junxiao Shi5bcab562017-07-16 17:19:14 +000031
32namespace detail {
33class MonotonicDeadlineTimer;
34} // namespace detail
35
Alexander Afanasyev9a9952f2015-01-28 19:06:48 -080036namespace scheduler {
Alexander Afanasyevf6468892014-01-29 01:04:14 -080037
Alexander Afanasyevf6468892014-01-29 01:04:14 -080038/**
Junxiao Shid50f2b42016-08-10 02:59:59 +000039 * \brief Function to be invoked when a scheduled event expires
Alexander Afanasyevf6468892014-01-29 01:04:14 -080040 */
Junxiao Shi5bcab562017-07-16 17:19:14 +000041using EventCallback = std::function<void()>;
Junxiao Shid50f2b42016-08-10 02:59:59 +000042
43/**
44 * \brief Stores internal information about a scheduled event
45 */
46class EventInfo;
47
48/**
49 * \brief Identifies a scheduled event
50 */
51class EventId
52{
53public:
54 /**
55 * \brief Constructs an empty EventId
56 * \note EventId is implicitly convertible from nullptr.
57 */
58 EventId(std::nullptr_t = nullptr)
59 {
60 }
61
62 /**
63 * \retval true The event is valid.
64 * \retval false This EventId is empty, or the event is expired or cancelled.
65 */
66 explicit
67 operator bool() const
68 {
69 return !this->operator!();
70 }
71
72 /**
73 * \retval true This EventId is empty, or the event is expired or cancelled.
74 * \retval false The event is valid.
75 */
76 bool
77 operator!() const;
78
79 /**
80 * \return whether this and other refer to the same event, or are both empty/expired/cancelled
81 */
82 bool
83 operator==(const EventId& other) const;
84
85 bool
86 operator!=(const EventId& other) const
87 {
88 return !this->operator==(other);
89 }
90
91 /**
92 * \brief clear this EventId
93 * \note This does not cancel the event.
94 * \post !(*this)
95 */
96 void
97 reset()
98 {
99 m_info.reset();
100 }
101
102private:
103 explicit
104 EventId(const weak_ptr<EventInfo>& info)
105 : m_info(info)
106 {
107 }
108
109private:
110 weak_ptr<EventInfo> m_info;
111
112 friend class Scheduler;
113 friend std::ostream& operator<<(std::ostream& os, const EventId& eventId);
114};
115
116std::ostream&
117operator<<(std::ostream& os, const EventId& eventId);
118
119class EventQueueCompare
120{
121public:
122 bool
123 operator()(const shared_ptr<EventInfo>& a, const shared_ptr<EventInfo>& b) const;
124};
125
Junxiao Shi5bcab562017-07-16 17:19:14 +0000126using EventQueue = std::multiset<shared_ptr<EventInfo>, EventQueueCompare>;
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800127
128/**
129 * \brief Generic scheduler
130 */
Junxiao Shid50f2b42016-08-10 02:59:59 +0000131class Scheduler : noncopyable
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800132{
133public:
Junxiao Shid50f2b42016-08-10 02:59:59 +0000134 explicit
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800135 Scheduler(boost::asio::io_service& ioService);
136
Junxiao Shi5bcab562017-07-16 17:19:14 +0000137 ~Scheduler();
138
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800139 /**
Junxiao Shid50f2b42016-08-10 02:59:59 +0000140 * \brief Schedule a one-time event after the specified delay
Junxiao Shi86dfa532016-08-10 03:00:11 +0000141 * \return EventId that can be used to cancel the scheduled event
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800142 */
143 EventId
Junxiao Shi5bcab562017-07-16 17:19:14 +0000144 scheduleEvent(time::nanoseconds after, const EventCallback& callback);
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800145
146 /**
Junxiao Shid50f2b42016-08-10 02:59:59 +0000147 * \brief Cancel a scheduled event
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800148 */
149 void
150 cancelEvent(const EventId& eventId);
151
Alexander Afanasyev7ae4bf52014-07-11 17:12:41 -0700152 /**
153 * \brief Cancel all scheduled events
154 */
155 void
156 cancelAllEvents();
157
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800158private:
Junxiao Shid50f2b42016-08-10 02:59:59 +0000159 /**
160 * \brief Schedule the next event on the deadline timer
161 */
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800162 void
Junxiao Shid50f2b42016-08-10 02:59:59 +0000163 scheduleNext();
164
Junxiao Shi86dfa532016-08-10 03:00:11 +0000165 /**
166 * \brief Execute expired events
167 * \note If an event callback throws, the exception is propagated to the thread running the
168 * io_service. In case there are other expired events, they will be processed in the next
169 * invocation of this method.
170 */
Junxiao Shid50f2b42016-08-10 02:59:59 +0000171 void
172 executeEvent(const boost::system::error_code& code);
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -0700173
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800174private:
Junxiao Shi5bcab562017-07-16 17:19:14 +0000175 unique_ptr<detail::MonotonicDeadlineTimer> m_deadlineTimer;
Junxiao Shid50f2b42016-08-10 02:59:59 +0000176 EventQueue m_queue;
Yingdi Yuf2a82092014-02-03 16:49:15 -0800177 bool m_isEventExecuting;
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800178};
179
Alexander Afanasyev9a9952f2015-01-28 19:06:48 -0800180} // namespace scheduler
181
182using util::scheduler::Scheduler;
183
184} // namespace util
185
186// for backwards compatibility
187using util::scheduler::Scheduler;
188using util::scheduler::EventId;
189
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800190} // namespace ndn
191
192#endif // NDN_UTIL_SCHEDULER_HPP