2 * Copyright 2016 Facebook, Inc.
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
21 #include <folly/io/async/AsyncTimeout.h>
22 #include <folly/io/async/EventBase.h>
23 #include <folly/io/async/EventUtil.h>
24 #include <folly/io/async/Request.h>
27 #include <glog/logging.h>
31 AsyncTimeout::AsyncTimeout(TimeoutManager* timeoutManager)
32 : timeoutManager_(timeoutManager) {
35 &event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
36 event_.ev_base = nullptr;
37 timeoutManager_->attachTimeoutManager(
39 TimeoutManager::InternalEnum::NORMAL);
40 RequestContext::saveContext();
43 AsyncTimeout::AsyncTimeout(EventBase* eventBase)
44 : timeoutManager_(eventBase) {
47 &event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
48 event_.ev_base = nullptr;
50 timeoutManager_->attachTimeoutManager(
52 TimeoutManager::InternalEnum::NORMAL);
54 RequestContext::saveContext();
57 AsyncTimeout::AsyncTimeout(TimeoutManager* timeoutManager,
58 InternalEnum internal)
59 : timeoutManager_(timeoutManager) {
62 &event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
63 event_.ev_base = nullptr;
64 timeoutManager_->attachTimeoutManager(this, internal);
65 RequestContext::saveContext();
68 AsyncTimeout::AsyncTimeout(EventBase* eventBase, InternalEnum internal)
69 : timeoutManager_(eventBase) {
72 &event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
73 event_.ev_base = nullptr;
74 timeoutManager_->attachTimeoutManager(this, internal);
75 RequestContext::saveContext();
78 AsyncTimeout::AsyncTimeout(): timeoutManager_(nullptr) {
80 &event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
81 event_.ev_base = nullptr;
82 RequestContext::saveContext();
85 AsyncTimeout::~AsyncTimeout() {
89 bool AsyncTimeout::scheduleTimeout(TimeoutManager::timeout_type timeout) {
90 assert(timeoutManager_ != nullptr);
91 context_ = RequestContext::saveContext();
92 return timeoutManager_->scheduleTimeout(this, timeout);
95 bool AsyncTimeout::scheduleTimeout(uint32_t milliseconds) {
96 return scheduleTimeout(TimeoutManager::timeout_type(milliseconds));
99 void AsyncTimeout::cancelTimeout() {
101 timeoutManager_->cancelTimeout(this);
105 bool AsyncTimeout::isScheduled() const {
106 return EventUtil::isEventRegistered(&event_);
109 void AsyncTimeout::attachTimeoutManager(
110 TimeoutManager* timeoutManager,
111 InternalEnum internal) {
112 // This also implies no timeout is scheduled.
113 assert(timeoutManager_ == nullptr);
114 assert(timeoutManager->isInTimeoutManagerThread());
115 timeoutManager_ = timeoutManager;
117 timeoutManager_->attachTimeoutManager(this, internal);
120 void AsyncTimeout::attachEventBase(
121 EventBase* eventBase,
122 InternalEnum internal) {
123 attachTimeoutManager(eventBase, internal);
126 void AsyncTimeout::detachTimeoutManager() {
127 // Only allow the event base to be changed if the timeout is not
128 // currently installed.
130 // Programmer bug. Abort the program.
131 LOG(ERROR) << "detachEventBase() called on scheduled timeout; aborting";
136 if (timeoutManager_) {
137 timeoutManager_->detachTimeoutManager(this);
138 timeoutManager_ = nullptr;
142 void AsyncTimeout::detachEventBase() {
143 detachTimeoutManager();
146 void AsyncTimeout::libeventCallback(libevent_fd_t fd, short events, void* arg) {
147 AsyncTimeout* timeout = reinterpret_cast<AsyncTimeout*>(arg);
148 assert(libeventFdToFd(fd) == -1);
149 assert(events == EV_TIMEOUT);
150 // prevent unused variable warnings
154 // double check that ev_flags gets reset when the timeout is not running
155 assert((event_ref_flags(&timeout->event_) & ~EVLIST_INTERNAL) == EVLIST_INIT);
157 // this can't possibly fire if timeout->eventBase_ is nullptr
158 timeout->timeoutManager_->bumpHandlingTime();
161 RequestContext::setContext(timeout->context_);
163 timeout->timeoutExpired();
165 RequestContext::setContext(old_ctx);