2 * Copyright 2014-present 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>
22 TimeoutController::TimeoutController(LoopController& loopController)
23 : nextTimeout_(TimePoint::max()), loopController_(loopController) {}
25 intptr_t TimeoutController::registerTimeout(
26 std::function<void()> f,
28 auto& list = [&]() -> TimeoutHandleList& {
29 for (auto& bucket : timeoutHandleBuckets_) {
30 if (bucket.first == duration) {
31 return *bucket.second;
35 timeoutHandleBuckets_.emplace_back(
36 duration, std::make_unique<TimeoutHandleList>());
37 return *timeoutHandleBuckets_.back().second;
40 auto timeout = Clock::now() + duration;
41 list.emplace(std::move(f), timeout, list);
43 if (timeout < nextTimeout_) {
44 nextTimeout_ = timeout;
48 return reinterpret_cast<intptr_t>(&list.back());
51 void TimeoutController::runTimeouts(TimePoint time) {
52 auto now = Clock::now();
53 // Make sure we don't skip some events if function was run before actual time.
57 if (nextTimeout_ > time) {
61 nextTimeout_ = TimePoint::max();
63 for (auto& bucket : timeoutHandleBuckets_) {
64 auto& list = *bucket.second;
66 while (!list.empty()) {
67 if (!list.front().canceled) {
68 if (list.front().timeout > time) {
69 nextTimeout_ = std::min(nextTimeout_, list.front().timeout);
79 if (nextTimeout_ != TimePoint::max()) {
84 void TimeoutController::scheduleRun() {
85 auto time = nextTimeout_;
86 std::weak_ptr<TimeoutController> timeoutControllerWeak = shared_from_this();
88 loopController_.timedSchedule(
89 [timeoutControllerWeak, time]() {
90 if (auto timeoutController = timeoutControllerWeak.lock()) {
91 timeoutController->runTimeouts(time);
97 void TimeoutController::cancel(intptr_t p) {
98 auto handle = reinterpret_cast<TimeoutHandle*>(p);
99 handle->canceled = true;
101 auto& list = handle->list;
103 while (!list.empty() && list.front().canceled) {
107 } // namespace fibers