2 * Copyright 2004-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.
17 #include <folly/io/async/AsyncTimeout.h>
18 #include <folly/io/async/EventBase.h>
19 #include <folly/io/async/EventUtil.h>
20 #include <folly/io/async/Request.h>
23 #include <glog/logging.h>
27 AsyncTimeout::AsyncTimeout(TimeoutManager* timeoutManager)
28 : timeoutManager_(timeoutManager) {
31 &event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
32 event_.ev_base = nullptr;
33 timeoutManager_->attachTimeoutManager(
35 TimeoutManager::InternalEnum::NORMAL);
38 AsyncTimeout::AsyncTimeout(EventBase* eventBase)
39 : timeoutManager_(eventBase) {
42 &event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
43 event_.ev_base = nullptr;
45 timeoutManager_->attachTimeoutManager(
47 TimeoutManager::InternalEnum::NORMAL);
51 AsyncTimeout::AsyncTimeout(TimeoutManager* timeoutManager,
52 InternalEnum internal)
53 : timeoutManager_(timeoutManager) {
56 &event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
57 event_.ev_base = nullptr;
58 timeoutManager_->attachTimeoutManager(this, internal);
61 AsyncTimeout::AsyncTimeout(EventBase* eventBase, InternalEnum internal)
62 : timeoutManager_(eventBase) {
65 &event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
66 event_.ev_base = nullptr;
67 timeoutManager_->attachTimeoutManager(this, internal);
70 AsyncTimeout::AsyncTimeout(): timeoutManager_(nullptr) {
72 &event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
73 event_.ev_base = nullptr;
76 AsyncTimeout::~AsyncTimeout() {
80 bool AsyncTimeout::scheduleTimeout(TimeoutManager::timeout_type timeout) {
81 assert(timeoutManager_ != nullptr);
82 context_ = RequestContext::saveContext();
83 return timeoutManager_->scheduleTimeout(this, timeout);
86 bool AsyncTimeout::scheduleTimeout(uint32_t milliseconds) {
87 return scheduleTimeout(TimeoutManager::timeout_type(milliseconds));
90 void AsyncTimeout::cancelTimeout() {
92 timeoutManager_->cancelTimeout(this);
96 bool AsyncTimeout::isScheduled() const {
97 return EventUtil::isEventRegistered(&event_);
100 void AsyncTimeout::attachTimeoutManager(
101 TimeoutManager* timeoutManager,
102 InternalEnum internal) {
103 // This also implies no timeout is scheduled.
104 assert(timeoutManager_ == nullptr);
105 assert(timeoutManager->isInTimeoutManagerThread());
106 timeoutManager_ = timeoutManager;
108 timeoutManager_->attachTimeoutManager(this, internal);
111 void AsyncTimeout::attachEventBase(
112 EventBase* eventBase,
113 InternalEnum internal) {
114 attachTimeoutManager(eventBase, internal);
117 void AsyncTimeout::detachTimeoutManager() {
118 // Only allow the event base to be changed if the timeout is not
119 // currently installed.
121 // Programmer bug. Abort the program.
122 LOG(FATAL) << "detachEventBase() called on scheduled timeout; aborting";
125 if (timeoutManager_) {
126 timeoutManager_->detachTimeoutManager(this);
127 timeoutManager_ = nullptr;
131 void AsyncTimeout::detachEventBase() {
132 detachTimeoutManager();
135 void AsyncTimeout::libeventCallback(libevent_fd_t fd, short events, void* arg) {
136 AsyncTimeout* timeout = reinterpret_cast<AsyncTimeout*>(arg);
137 assert(libeventFdToFd(fd) == -1);
138 assert(events == EV_TIMEOUT);
139 // prevent unused variable warnings
143 // double check that ev_flags gets reset when the timeout is not running
144 assert((event_ref_flags(&timeout->event_) & ~EVLIST_INTERNAL) == EVLIST_INIT);
146 // this can't possibly fire if timeout->eventBase_ is nullptr
147 timeout->timeoutManager_->bumpHandlingTime();
149 RequestContextScopeGuard rctx(timeout->context_);
151 timeout->timeoutExpired();