blob: bd4467aa5578f2f3cb1da46ef044d137b1f9ff91 [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/*
Davide Pesavento5afbb0b2018-01-01 17:24:18 -05003 * Copyright (c) 2013-2018 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"
Davide Pesavento4d0d0962017-12-19 22:23:14 -050026#include "../net/asio-fwd.hpp"
Davide Pesaventobdcedf42017-10-15 14:56:28 -040027
Davide Pesavento5afbb0b2018-01-01 17:24:18 -050028#include <boost/system/error_code.hpp>
Davide Pesaventobdcedf42017-10-15 14:56:28 -040029#include <set>
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070030
Alexander Afanasyevf6468892014-01-29 01:04:14 -080031namespace ndn {
Alexander Afanasyev9a9952f2015-01-28 19:06:48 -080032namespace util {
Junxiao Shi5bcab562017-07-16 17:19:14 +000033
34namespace detail {
Davide Pesavento5afbb0b2018-01-01 17:24:18 -050035class SteadyTimer;
Junxiao Shi5bcab562017-07-16 17:19:14 +000036} // namespace detail
37
Alexander Afanasyev9a9952f2015-01-28 19:06:48 -080038namespace scheduler {
Alexander Afanasyevf6468892014-01-29 01:04:14 -080039
Alexander Afanasyevf6468892014-01-29 01:04:14 -080040/**
Junxiao Shid50f2b42016-08-10 02:59:59 +000041 * \brief Function to be invoked when a scheduled event expires
Alexander Afanasyevf6468892014-01-29 01:04:14 -080042 */
Junxiao Shi5bcab562017-07-16 17:19:14 +000043using EventCallback = std::function<void()>;
Junxiao Shid50f2b42016-08-10 02:59:59 +000044
45/**
46 * \brief Stores internal information about a scheduled event
47 */
48class EventInfo;
49
50/**
51 * \brief Identifies a scheduled event
52 */
53class EventId
54{
55public:
56 /**
57 * \brief Constructs an empty EventId
58 * \note EventId is implicitly convertible from nullptr.
59 */
Davide Pesavento3a3e1882018-07-17 14:49:15 -040060 constexpr
61 EventId(std::nullptr_t = nullptr) noexcept
Junxiao Shid50f2b42016-08-10 02:59:59 +000062 {
63 }
64
65 /**
66 * \retval true The event is valid.
67 * \retval false This EventId is empty, or the event is expired or cancelled.
68 */
69 explicit
Davide Pesavento3a3e1882018-07-17 14:49:15 -040070 operator bool() const noexcept;
Junxiao Shid50f2b42016-08-10 02:59:59 +000071
72 /**
73 * \return whether this and other refer to the same event, or are both empty/expired/cancelled
74 */
75 bool
Davide Pesavento3a3e1882018-07-17 14:49:15 -040076 operator==(const EventId& other) const noexcept;
Junxiao Shid50f2b42016-08-10 02:59:59 +000077
78 bool
Davide Pesavento3a3e1882018-07-17 14:49:15 -040079 operator!=(const EventId& other) const noexcept
Junxiao Shid50f2b42016-08-10 02:59:59 +000080 {
81 return !this->operator==(other);
82 }
83
84 /**
85 * \brief clear this EventId
86 * \note This does not cancel the event.
87 * \post !(*this)
88 */
89 void
Davide Pesavento3a3e1882018-07-17 14:49:15 -040090 reset() noexcept
Junxiao Shid50f2b42016-08-10 02:59:59 +000091 {
92 m_info.reset();
93 }
94
95private:
96 explicit
Davide Pesavento3a3e1882018-07-17 14:49:15 -040097 EventId(weak_ptr<EventInfo> info) noexcept
98 : m_info(std::move(info))
Junxiao Shid50f2b42016-08-10 02:59:59 +000099 {
100 }
101
102private:
103 weak_ptr<EventInfo> m_info;
104
105 friend class Scheduler;
106 friend std::ostream& operator<<(std::ostream& os, const EventId& eventId);
107};
108
109std::ostream&
110operator<<(std::ostream& os, const EventId& eventId);
111
112class EventQueueCompare
113{
114public:
115 bool
Davide Pesavento3a3e1882018-07-17 14:49:15 -0400116 operator()(const shared_ptr<EventInfo>& a, const shared_ptr<EventInfo>& b) const noexcept;
Junxiao Shid50f2b42016-08-10 02:59:59 +0000117};
118
Junxiao Shi5bcab562017-07-16 17:19:14 +0000119using EventQueue = std::multiset<shared_ptr<EventInfo>, EventQueueCompare>;
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800120
121/**
122 * \brief Generic scheduler
123 */
Junxiao Shid50f2b42016-08-10 02:59:59 +0000124class Scheduler : noncopyable
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800125{
126public:
Junxiao Shid50f2b42016-08-10 02:59:59 +0000127 explicit
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800128 Scheduler(boost::asio::io_service& ioService);
129
Junxiao Shi5bcab562017-07-16 17:19:14 +0000130 ~Scheduler();
131
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800132 /**
Junxiao Shid50f2b42016-08-10 02:59:59 +0000133 * \brief Schedule a one-time event after the specified delay
Junxiao Shi86dfa532016-08-10 03:00:11 +0000134 * \return EventId that can be used to cancel the scheduled event
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800135 */
136 EventId
Junxiao Shi5bcab562017-07-16 17:19:14 +0000137 scheduleEvent(time::nanoseconds after, const EventCallback& callback);
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800138
139 /**
Junxiao Shid50f2b42016-08-10 02:59:59 +0000140 * \brief Cancel a scheduled event
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800141 */
142 void
143 cancelEvent(const EventId& eventId);
144
Alexander Afanasyev7ae4bf52014-07-11 17:12:41 -0700145 /**
146 * \brief Cancel all scheduled events
147 */
148 void
149 cancelAllEvents();
150
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800151private:
Junxiao Shid50f2b42016-08-10 02:59:59 +0000152 /**
153 * \brief Schedule the next event on the deadline timer
154 */
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800155 void
Junxiao Shid50f2b42016-08-10 02:59:59 +0000156 scheduleNext();
157
Junxiao Shi86dfa532016-08-10 03:00:11 +0000158 /**
159 * \brief Execute expired events
160 * \note If an event callback throws, the exception is propagated to the thread running the
161 * io_service. In case there are other expired events, they will be processed in the next
162 * invocation of this method.
163 */
Junxiao Shid50f2b42016-08-10 02:59:59 +0000164 void
165 executeEvent(const boost::system::error_code& code);
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -0700166
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800167private:
Davide Pesavento5afbb0b2018-01-01 17:24:18 -0500168 unique_ptr<detail::SteadyTimer> m_timer;
Junxiao Shid50f2b42016-08-10 02:59:59 +0000169 EventQueue m_queue;
Yingdi Yuf2a82092014-02-03 16:49:15 -0800170 bool m_isEventExecuting;
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800171};
172
Alexander Afanasyev9a9952f2015-01-28 19:06:48 -0800173} // namespace scheduler
174
175using util::scheduler::Scheduler;
176
177} // namespace util
178
179// for backwards compatibility
180using util::scheduler::Scheduler;
181using util::scheduler::EventId;
182
Alexander Afanasyevf6468892014-01-29 01:04:14 -0800183} // namespace ndn
184
185#endif // NDN_UTIL_SCHEDULER_HPP