proxygen
HHWheelTimer.h
Go to the documentation of this file.
1 /*
2  * Copyright 2014-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <folly/Optional.h>
22 
23 #include <boost/intrusive/list.hpp>
24 #include <glog/logging.h>
25 
26 #include <chrono>
27 #include <cstddef>
28 #include <list>
29 #include <memory>
30 
31 namespace folly {
32 
56  public:
57  using UniquePtr = std::unique_ptr<HHWheelTimer, Destructor>;
58  using SharedPtr = std::shared_ptr<HHWheelTimer>;
59 
60  template <typename... Args>
61  static UniquePtr newTimer(Args&&... args) {
62  return UniquePtr(new HHWheelTimer(std::forward<Args>(args)...));
63  }
64 
68  class Callback
69  : public boost::intrusive::list_base_hook<
70  boost::intrusive::link_mode<boost::intrusive::auto_unlink>> {
71  public:
72  Callback() = default;
73  virtual ~Callback();
74 
78  virtual void timeoutExpired() noexcept = 0;
79 
83  virtual void callbackCanceled() noexcept {
85  }
86 
92  void cancelTimeout() {
93  if (wheel_ == nullptr) {
94  // We're not scheduled, so there's nothing to do.
95  return;
96  }
98  }
99 
103  bool isScheduled() const {
104  return wheel_ != nullptr;
105  }
106 
112  std::chrono::milliseconds getTimeRemaining() {
113  return getTimeRemaining(getCurTime());
114  }
115 
116  protected:
121  virtual std::chrono::steady_clock::time_point getCurTime() {
123  }
124 
125  private:
126  // Get the time remaining until this timeout expires
127  std::chrono::milliseconds getTimeRemaining(
128  std::chrono::steady_clock::time_point now) const {
129  if (now >= expiration_) {
130  return std::chrono::milliseconds(0);
131  }
132  return std::chrono::duration_cast<std::chrono::milliseconds>(
133  expiration_ - now);
134  }
135 
136  void setScheduled(HHWheelTimer* wheel, std::chrono::milliseconds);
137  void cancelTimeoutImpl();
138 
139  HHWheelTimer* wheel_{nullptr};
140  std::chrono::steady_clock::time_point expiration_{};
141  int bucket_{-1};
142 
143  typedef boost::intrusive::
144  list<Callback, boost::intrusive::constant_time_size<false>>
146 
147  std::shared_ptr<RequestContext> requestContext_;
148 
149  // Give HHWheelTimer direct access to our members so it can take care
150  // of scheduling/cancelling.
151  friend class HHWheelTimer;
152  };
153 
164  explicit HHWheelTimer(
165  folly::TimeoutManager* timeoutManager,
166  std::chrono::milliseconds intervalMS =
167  std::chrono::milliseconds(DEFAULT_TICK_INTERVAL),
169  std::chrono::milliseconds defaultTimeoutMS =
170  std::chrono::milliseconds(-1));
171 
177  size_t cancelAll();
178 
184  std::chrono::milliseconds getTickInterval() const {
185  return interval_;
186  }
187 
193  std::chrono::milliseconds getDefaultTimeout() const {
194  return defaultTimeout_;
195  }
196 
200  void setDefaultTimeout(std::chrono::milliseconds timeout) {
201  defaultTimeout_ = timeout;
202  }
203 
211  void scheduleTimeout(Callback* callback, std::chrono::milliseconds timeout);
212  void scheduleTimeoutImpl(
213  Callback* callback,
214  std::chrono::milliseconds timeout);
215 
226  void scheduleTimeout(Callback* callback);
227 
228  template <class F>
229  void scheduleTimeoutFn(F fn, std::chrono::milliseconds timeout) {
230  struct Wrapper : Callback {
231  Wrapper(F f) : fn_(std::move(f)) {}
232  void timeoutExpired() noexcept override {
233  try {
234  fn_();
235  } catch (std::exception const& e) {
236  LOG(ERROR) << "HHWheelTimer timeout callback threw an exception: "
237  << e.what();
238  } catch (...) {
239  LOG(ERROR) << "HHWheelTimer timeout callback threw a non-exception.";
240  }
241  delete this;
242  }
243  F fn_;
244  };
245  Wrapper* w = new Wrapper(std::move(fn));
246  scheduleTimeout(w, timeout);
247  }
248 
252  std::size_t count() const {
253  return count_;
254  }
255 
256  bool isDetachable() const {
258  }
259 
263 
264  protected:
271  ~HHWheelTimer() override;
272 
273  private:
274  // Forbidden copy constructor and assignment operator
275  HHWheelTimer(HHWheelTimer const&) = delete;
276  HHWheelTimer& operator=(HHWheelTimer const&) = delete;
277 
278  // Methods inherited from AsyncTimeout
279  void timeoutExpired() noexcept override;
280 
281  std::chrono::milliseconds interval_;
282  std::chrono::milliseconds defaultTimeout_;
283 
284  static constexpr int WHEEL_BUCKETS = 4;
285  static constexpr int WHEEL_BITS = 8;
286  static constexpr unsigned int WHEEL_SIZE = (1 << WHEEL_BITS);
287  static constexpr unsigned int WHEEL_MASK = (WHEEL_SIZE - 1);
288  static constexpr uint32_t LARGEST_SLOT = 0xffffffffUL;
289 
292  std::vector<std::size_t> bitmap_;
293 
294  int64_t timeToWheelTicks(std::chrono::milliseconds t) {
295  return t.count() / interval_.count();
296  }
297 
298  bool cascadeTimers(int bucket, int tick);
301  std::size_t count_;
302  std::chrono::steady_clock::time_point startTime_;
303 
305 
306  void scheduleNextTimeout();
307 
309  CallbackList timeouts; // Timeouts queued to run
310 
311  std::chrono::steady_clock::time_point getCurTime() {
313  }
314 };
315 
316 } // namespace folly
static constexpr unsigned int WHEEL_MASK
Definition: HHWheelTimer.h:287
auto f
static constexpr int WHEEL_BUCKETS
Definition: HHWheelTimer.h:284
static constexpr int WHEEL_BITS
Definition: HHWheelTimer.h:285
virtual void callbackCanceled() noexcept
Definition: HHWheelTimer.h:83
static constexpr uint32_t LARGEST_SLOT
Definition: HHWheelTimer.h:288
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
std::chrono::steady_clock::time_point now()
const TimeoutManager * getTimeoutManager()
Definition: AsyncTimeout.h:143
boost::intrusive::list< Callback, boost::intrusive::constant_time_size< false > > List
Definition: HHWheelTimer.h:145
std::vector< std::size_t > bitmap_
Definition: HHWheelTimer.h:292
void setDefaultTimeout(std::chrono::milliseconds timeout)
Definition: HHWheelTimer.h:200
internal::ArgsMatcher< InnerMatcher > Args(const InnerMatcher &matcher)
std::chrono::milliseconds getTimeRemaining()
Definition: HHWheelTimer.h:112
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
static int DEFAULT_TICK_INTERVAL
Definition: HHWheelTimer.h:163
requires E e noexcept(noexcept(s.error(std::move(e))))
HHWheelTimer(folly::TimeoutManager *timeoutManager, std::chrono::milliseconds intervalMS=std::chrono::milliseconds(DEFAULT_TICK_INTERVAL), AsyncTimeout::InternalEnum internal=AsyncTimeout::InternalEnum::NORMAL, std::chrono::milliseconds defaultTimeoutMS=std::chrono::milliseconds(-1))
void scheduleTimeout(Callback *callback, std::chrono::milliseconds timeout)
std::shared_ptr< HHWheelTimer > SharedPtr
Definition: HHWheelTimer.h:58
std::chrono::steady_clock::time_point startTime_
Definition: HHWheelTimer.h:302
CallbackList buckets_[WHEEL_BUCKETS][WHEEL_SIZE]
Definition: HHWheelTimer.h:291
static UniquePtr newTimer(Args &&...args)
Definition: HHWheelTimer.h:61
std::shared_ptr< RequestContext > requestContext_
Definition: HHWheelTimer.h:147
bool isDetachable() const
Definition: HHWheelTimer.h:256
void setScheduled(HHWheelTimer *wheel, std::chrono::milliseconds)
void scheduleTimeoutImpl(Callback *callback, std::chrono::milliseconds timeout)
static constexpr unsigned int WHEEL_SIZE
Definition: HHWheelTimer.h:286
void scheduleTimeoutFn(F fn, std::chrono::milliseconds timeout)
Definition: HHWheelTimer.h:229
virtual std::chrono::steady_clock::time_point getCurTime()
Definition: HHWheelTimer.h:121
std::unique_ptr< HHWheelTimer, Destructor > UniquePtr
Definition: HHWheelTimer.h:57
std::chrono::steady_clock::time_point expiration_
Definition: HHWheelTimer.h:140
bool * processingCallbacksGuard_
Definition: HHWheelTimer.h:308
void attachEventBase(EventBase *eventBase, InternalEnum internal=InternalEnum::NORMAL)
CallbackList timeouts
Definition: HHWheelTimer.h:309
std::chrono::milliseconds defaultTimeout_
Definition: HHWheelTimer.h:282
int64_t timeToWheelTicks(std::chrono::milliseconds t)
Definition: HHWheelTimer.h:294
std::chrono::milliseconds getTimeRemaining(std::chrono::steady_clock::time_point now) const
Definition: HHWheelTimer.h:127
~HHWheelTimer() override
HHWheelTimer & operator=(HHWheelTimer const &)=delete
std::chrono::milliseconds getTickInterval() const
Definition: HHWheelTimer.h:184
bool isScheduled() const
std::size_t count() const
Definition: HHWheelTimer.h:252
Callback::List CallbackList
Definition: HHWheelTimer.h:290
std::chrono::milliseconds getDefaultTimeout() const
Definition: HHWheelTimer.h:193
bool cascadeTimers(int bucket, int tick)
virtual void timeoutExpired() noexcept=0
std::size_t count_
Definition: HHWheelTimer.h:301
std::chrono::milliseconds interval_
Definition: HHWheelTimer.h:281
std::chrono::steady_clock::time_point getCurTime()
Definition: HHWheelTimer.h:311