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 "TimeoutController.h"
17 #include <folly/Memory.h>
19 namespace folly { namespace fibers {
21 TimeoutController::TimeoutController(LoopController& loopController) :
22 nextTimeout_(TimePoint::max()),
23 loopController_(loopController) {}
25 intptr_t TimeoutController::registerTimeout(std::function<void()> f,
27 auto& list = [&]() -> TimeoutHandleList& {
28 for (auto& bucket : timeoutHandleBuckets_) {
29 if (bucket.first == duration) {
30 return *bucket.second;
34 timeoutHandleBuckets_.emplace_back(duration,
35 folly::make_unique<TimeoutHandleList>());
36 return *timeoutHandleBuckets_.back().second;
39 auto timeout = Clock::now() + duration;
40 list.emplace(std::move(f), timeout, list);
42 if (timeout < nextTimeout_) {
43 nextTimeout_ = timeout;
47 return reinterpret_cast<intptr_t>(&list.back());
50 void TimeoutController::runTimeouts(TimePoint time) {
51 auto now = Clock::now();
52 // Make sure we don't skip some events if function was run before actual time.
56 if (nextTimeout_ > time) {
60 nextTimeout_ = TimePoint::max();
62 for (auto& bucket : timeoutHandleBuckets_) {
63 auto& list = *bucket.second;
65 while (!list.empty()) {
66 if (!list.front().canceled) {
67 if (list.front().timeout > time) {
68 nextTimeout_ = std::min(nextTimeout_, list.front().timeout);
78 if (nextTimeout_ != TimePoint::max()) {
83 void TimeoutController::scheduleRun() {
84 auto time = nextTimeout_;
85 std::weak_ptr<TimeoutController> timeoutControllerWeak = shared_from_this();
87 loopController_.timedSchedule([timeoutControllerWeak, time]() {
88 if (auto timeoutController = timeoutControllerWeak.lock()) {
89 timeoutController->runTimeouts(time);
94 void TimeoutController::cancel(intptr_t p) {
95 auto handle = reinterpret_cast<TimeoutHandle*>(p);
96 handle->canceled = true;
98 auto& list = handle->list;
100 while (!list.empty() && list.front().canceled) {