(folly) have Try::moveFromTry take an lvalue
[folly.git] / folly / futures / ThreadWheelTimekeeper.cpp
1 /*
2  * Copyright 2015 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 #include "ThreadWheelTimekeeper.h"
17
18 #include <folly/Singleton.h>
19 #include <folly/futures/Future.h>
20 #include <future>
21
22 namespace folly {
23
24 namespace {
25   Singleton<ThreadWheelTimekeeper> timekeeperSingleton_;
26
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(EventBase* base) {
31       // optimization opportunity: memory pool
32       return new WTCallback(base);
33     }
34
35     Future<Unit> getFuture() {
36       return promise_.getFuture();
37     }
38
39    protected:
40     EventBase* base_;
41     Promise<Unit> promise_;
42
43     explicit WTCallback(EventBase* base)
44         : base_(base) {
45       promise_.setInterruptHandler(
46         std::bind(&WTCallback::interruptHandler, this));
47     }
48
49     void timeoutExpired() noexcept override {
50       promise_.setValue();
51       delete this;
52     }
53
54     void interruptHandler() {
55       base_->runInEventBaseThread([=] {
56         cancelTimeout();
57         delete this;
58       });
59     }
60   };
61
62 } // namespace
63
64
65 ThreadWheelTimekeeper::ThreadWheelTimekeeper() :
66   thread_([this]{ eventBase_.loopForever(); }),
67   wheelTimer_(new HHWheelTimer(&eventBase_, std::chrono::milliseconds(1)))
68 {
69   eventBase_.waitUntilRunning();
70   eventBase_.runInEventBaseThread([this]{
71     // 15 characters max
72     eventBase_.setName("FutureTimekeepr");
73   });
74 }
75
76 ThreadWheelTimekeeper::~ThreadWheelTimekeeper() {
77   eventBase_.runInEventBaseThreadAndWait([this]{
78     wheelTimer_->cancelAll();
79     eventBase_.terminateLoopSoon();
80   });
81   thread_.join();
82 }
83
84 Future<Unit> ThreadWheelTimekeeper::after(Duration dur) {
85   auto cob = WTCallback::create(&eventBase_);
86   auto f = cob->getFuture();
87   eventBase_.runInEventBaseThread([=]{
88     wheelTimer_->scheduleTimeout(cob, dur);
89   });
90   return f;
91 }
92
93 namespace detail {
94
95 Timekeeper* getTimekeeperSingleton() {
96   return timekeeperSingleton_.get();
97 }
98
99 } // detail
100
101 } // folly