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.
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);
97 bool AsyncTimeout::isScheduled() const {
98 return EventUtil::isEventRegistered(&event_);
101 void AsyncTimeout::attachTimeoutManager(
102 TimeoutManager* timeoutManager,
103 InternalEnum internal) {
104 // This also implies no timeout is scheduled.
105 assert(timeoutManager_ == nullptr);
106 assert(timeoutManager->isInTimeoutManagerThread());
107 timeoutManager_ = timeoutManager;
109 timeoutManager_->attachTimeoutManager(this, internal);
112 void AsyncTimeout::attachEventBase(
113 EventBase* eventBase,
114 InternalEnum internal) {
115 attachTimeoutManager(eventBase, internal);
118 void AsyncTimeout::detachTimeoutManager() {
119 // Only allow the event base to be changed if the timeout is not
120 // currently installed.
122 // Programmer bug. Abort the program.
123 LOG(FATAL) << "detachEventBase() called on scheduled timeout; aborting";
126 if (timeoutManager_) {
127 timeoutManager_->detachTimeoutManager(this);
128 timeoutManager_ = nullptr;
132 void AsyncTimeout::detachEventBase() {
133 detachTimeoutManager();
136 void AsyncTimeout::libeventCallback(libevent_fd_t fd, short events, void* arg) {
137 AsyncTimeout* timeout = reinterpret_cast<AsyncTimeout*>(arg);
138 assert(libeventFdToFd(fd) == -1);
139 assert(events == EV_TIMEOUT);
140 // prevent unused variable warnings
144 // double check that ev_flags gets reset when the timeout is not running
145 assert((event_ref_flags(&timeout->event_) & ~EVLIST_INTERNAL) == EVLIST_INIT);
147 // this can't possibly fire if timeout->eventBase_ is nullptr
148 timeout->timeoutManager_->bumpHandlingTime();
150 RequestContextScopeGuard rctx(timeout->context_);
152 timeout->timeoutExpired();