Kea  2.3.9
interval_timer.cc
Go to the documentation of this file.
1 // Copyright (C) 2011-2023 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #include <config.h>
10 #include <asiolink/io_service.h>
11 
12 #include <boost/enable_shared_from_this.hpp>
13 #include <boost/noncopyable.hpp>
14 #include <boost/shared_ptr.hpp>
15 
16 #include <exceptions/exceptions.h>
17 
18 #include <atomic>
19 #include <functional>
20 #include <mutex>
21 
22 using namespace std;
23 namespace ph = std::placeholders;
24 
25 namespace isc {
26 namespace asiolink {
27 
36  public boost::enable_shared_from_this<IntervalTimerImpl>,
37  public boost::noncopyable {
38 public:
39 
43  IntervalTimerImpl(IOService& io_service);
44 
47 
53  void setup(const IntervalTimer::Callback& cbfunc, const long interval,
54  const IntervalTimer::Mode& interval_mode
55  = IntervalTimer::REPEATING);
56 
60  void callback(const boost::system::error_code& error);
61 
63  void cancel() {
64  lock_guard<mutex> lk (mutex_);
65  timer_.cancel();
66  interval_ = 0;
67  cbfunc_ = std::function<void()>();
68  }
69 
73  long getInterval() const { return (interval_); }
74 
75 private:
76 
80  void update();
81 
84 
86  std::atomic<long> interval_;
87 
89  boost::asio::deadline_timer timer_;
90 
93 
95  std::mutex mutex_;
96 
101  static const long INVALIDATED_INTERVAL = -1;
102 };
103 
104 IntervalTimerImpl::IntervalTimerImpl(IOService& io_service) :
105  interval_(0), timer_(io_service.get_io_service()),
106  mode_(IntervalTimer::REPEATING) {
107 }
108 
110  interval_ = INVALIDATED_INTERVAL;
111 }
112 
113 void
115  const long interval,
116  const IntervalTimer::Mode& mode) {
117  // Interval should not be less than 0.
118  if (interval < 0) {
119  isc_throw(isc::BadValue, "Interval should not be less than or "
120  "equal to 0");
121  }
122  // Call back function should not be empty.
123  if (!cbfunc) {
124  isc_throw(isc::InvalidParameter, "Callback function is empty");
125  }
126 
127  lock_guard<mutex> lk(mutex_);
128  cbfunc_ = cbfunc;
129  interval_ = interval;
130  mode_ = mode;
131 
132  // Set initial expire time.
133  // At this point the timer is not running yet and will not expire.
134  // After calling IOService::run(), the timer will expire.
135  update();
136 }
137 
138 void
139 IntervalTimerImpl::update() {
140  try {
141  // Update expire time to (current time + interval_).
142  timer_.expires_from_now(boost::posix_time::millisec(long(interval_)));
143  // Reset timer.
144  // Pass a function bound with a shared_ptr to this.
145  timer_.async_wait(std::bind(&IntervalTimerImpl::callback,
146  shared_from_this(),
147  ph::_1)); //error
148  } catch (const boost::system::system_error& e) {
149  isc_throw(isc::Unexpected, "Failed to update timer: " << e.what());
150  } catch (const boost::bad_weak_ptr&) {
151  // Can't happen. It means a severe internal bug.
152  }
153 }
154 
155 void
156 IntervalTimerImpl::callback(const boost::system::error_code& ec) {
157  if (interval_ == INVALIDATED_INTERVAL) {
158  isc_throw(isc::BadValue, "Interval internal state");
159  }
160  if (interval_ == 0 || ec) {
161  // timer has been canceled. Do nothing.
162  } else {
163  {
164  lock_guard<mutex> lk(mutex_);
165  // If we should repeat, set next expire time.
166  if (mode_ == IntervalTimer::REPEATING) {
167  update();
168  }
169  }
170 
171  // Invoke the call back function.
172  cbfunc_();
173  }
174 }
175 
176 IntervalTimer::IntervalTimer(IOService& io_service) :
177  impl_(new IntervalTimerImpl(io_service)) {
178 }
179 
181  // Cancel the timer to make sure cbfunc_() will not be called any more.
182  cancel();
183 }
184 
185 void
186 IntervalTimer::setup(const Callback& cbfunc, const long interval,
187  const IntervalTimer::Mode& mode) {
188  return (impl_->setup(cbfunc, interval, mode));
189 }
190 
191 void
193  impl_->cancel();
194 }
195 
196 long
198  return (impl_->getInterval());
199 }
200 
201 } // namespace asiolink
202 } // namespace isc
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown if a parameter given to a method or function is considered invalid...
A generic exception that is thrown when an unexpected error condition occurs.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
@ error
Definition: db_log.h:116
Defines the logger used by the top-level component of kea-lfc.
CompressMode mode_
Definition: rdatafields.cc:97