2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
19 #include "folly/io/async/AsyncTimeout.h"
20 #include "folly/io/async/EventBase.h"
21 #include "folly/io/async/EventUtil.h"
22 #include "folly/io/async/Request.h"
25 #include <glog/logging.h>
29 AsyncTimeout::AsyncTimeout(TimeoutManager* timeoutManager)
30 : timeoutManager_(timeoutManager) {
32 event_set(&event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
33 event_.ev_base = nullptr;
34 timeoutManager_->attachTimeoutManager(
36 TimeoutManager::InternalEnum::NORMAL);
37 RequestContext::getStaticContext();
40 AsyncTimeout::AsyncTimeout(EventBase* eventBase)
41 : timeoutManager_(eventBase) {
43 event_set(&event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
44 event_.ev_base = nullptr;
45 timeoutManager_->attachTimeoutManager(
47 TimeoutManager::InternalEnum::NORMAL);
48 RequestContext::getStaticContext();
51 AsyncTimeout::AsyncTimeout(TimeoutManager* timeoutManager,
52 InternalEnum internal)
53 : timeoutManager_(timeoutManager) {
55 event_set(&event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
56 event_.ev_base = nullptr;
57 timeoutManager_->attachTimeoutManager(this, internal);
58 RequestContext::getStaticContext();
61 AsyncTimeout::AsyncTimeout(EventBase* eventBase, InternalEnum internal)
62 : timeoutManager_(eventBase) {
64 event_set(&event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
65 event_.ev_base = nullptr;
66 timeoutManager_->attachTimeoutManager(this, internal);
67 RequestContext::getStaticContext();
70 AsyncTimeout::AsyncTimeout(): timeoutManager_(nullptr) {
71 event_set(&event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
72 event_.ev_base = nullptr;
73 RequestContext::getStaticContext();
76 AsyncTimeout::~AsyncTimeout() {
80 bool AsyncTimeout::scheduleTimeout(std::chrono::milliseconds 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(std::chrono::milliseconds(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(ERROR) << "detachEventBase() called on scheduled timeout; aborting";
127 if (timeoutManager_) {
128 timeoutManager_->detachTimeoutManager(this);
129 timeoutManager_ = nullptr;
133 void AsyncTimeout::detachEventBase() {
134 detachTimeoutManager();
137 void AsyncTimeout::libeventCallback(int fd, short events, void* arg) {
138 AsyncTimeout* timeout = reinterpret_cast<AsyncTimeout*>(arg);
140 assert(events == EV_TIMEOUT);
142 // double check that ev_flags gets reset when the timeout is not running
143 assert((timeout->event_.ev_flags & ~EVLIST_INTERNAL) == EVLIST_INIT);
145 // this can't possibly fire if timeout->eventBase_ is nullptr
146 (void) timeout->timeoutManager_->bumpHandlingTime();
149 RequestContext::setContext(timeout->context_);
151 timeout->timeoutExpired();
153 RequestContext::setContext(old_ctx);