2 * Copyright 2015 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 #include "ThreadWheelTimekeeper.h"
18 #include <folly/experimental/Singleton.h>
19 #include <folly/futures/Future.h>
22 namespace folly { namespace detail {
25 Singleton<ThreadWheelTimekeeper> timekeeperSingleton_;
27 // Our Callback object for HHWheelTimer
28 struct WTCallback : public folly::HHWheelTimer::Callback {
29 // Only allow creation by this factory, to ensure heap allocation.
30 static WTCallback* create() {
31 // optimization opportunity: memory pool
32 return new WTCallback();
35 Future<void> getFuture() {
36 return promise_.getFuture();
40 Promise<void> promise_;
42 explicit WTCallback() {
43 promise_.setInterruptHandler(
44 std::bind(&WTCallback::interruptHandler, this));
47 void timeoutExpired() noexcept override {
52 void interruptHandler() {
61 ThreadWheelTimekeeper::ThreadWheelTimekeeper() :
62 thread_([this]{ eventBase_.loopForever(); }),
63 wheelTimer_(new HHWheelTimer(&eventBase_, std::chrono::milliseconds(1)))
65 eventBase_.waitUntilRunning();
66 eventBase_.runInEventBaseThread([this]{
68 eventBase_.setName("FutureTimekeepr");
72 ThreadWheelTimekeeper::~ThreadWheelTimekeeper() {
73 eventBase_.runInEventBaseThreadAndWait([this]{
74 wheelTimer_->cancelAll();
76 eventBase_.terminateLoopSoon();
80 Future<void> ThreadWheelTimekeeper::after(Duration dur) {
81 auto cob = WTCallback::create();
82 auto f = cob->getFuture();
83 eventBase_.runInEventBaseThread([=]{
84 wheelTimer_->scheduleTimeout(cob, dur);
89 Timekeeper* getTimekeeperSingleton() {
90 return timekeeperSingleton_.get();