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) {
34 event_set(&event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
35 event_.ev_base = nullptr;
36 timeoutManager_->attachTimeoutManager(
38 TimeoutManager::InternalEnum::NORMAL);
39 RequestContext::saveContext();
42 AsyncTimeout::AsyncTimeout(EventBase* eventBase)
43 : timeoutManager_(eventBase) {
45 event_set(&event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
46 event_.ev_base = nullptr;
48 timeoutManager_->attachTimeoutManager(
50 TimeoutManager::InternalEnum::NORMAL);
52 RequestContext::saveContext();
55 AsyncTimeout::AsyncTimeout(TimeoutManager* timeoutManager,
56 InternalEnum internal)
57 : timeoutManager_(timeoutManager) {
59 event_set(&event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
60 event_.ev_base = nullptr;
61 timeoutManager_->attachTimeoutManager(this, internal);
62 RequestContext::saveContext();
65 AsyncTimeout::AsyncTimeout(EventBase* eventBase, InternalEnum internal)
66 : timeoutManager_(eventBase) {
68 event_set(&event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
69 event_.ev_base = nullptr;
70 timeoutManager_->attachTimeoutManager(this, internal);
71 RequestContext::saveContext();
74 AsyncTimeout::AsyncTimeout(): timeoutManager_(nullptr) {
75 event_set(&event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
76 event_.ev_base = nullptr;
77 RequestContext::saveContext();
80 AsyncTimeout::~AsyncTimeout() {
84 bool AsyncTimeout::scheduleTimeout(TimeoutManager::timeout_type timeout) {
85 assert(timeoutManager_ != nullptr);
86 context_ = RequestContext::saveContext();
87 return timeoutManager_->scheduleTimeout(this, timeout);
90 bool AsyncTimeout::scheduleTimeout(uint32_t milliseconds) {
91 return scheduleTimeout(TimeoutManager::timeout_type(milliseconds));
94 void AsyncTimeout::cancelTimeout() {
96 timeoutManager_->cancelTimeout(this);
100 bool AsyncTimeout::isScheduled() const {
101 return EventUtil::isEventRegistered(&event_);
104 void AsyncTimeout::attachTimeoutManager(
105 TimeoutManager* timeoutManager,
106 InternalEnum internal) {
107 // This also implies no timeout is scheduled.
108 assert(timeoutManager_ == nullptr);
109 assert(timeoutManager->isInTimeoutManagerThread());
110 timeoutManager_ = timeoutManager;
112 timeoutManager_->attachTimeoutManager(this, internal);
115 void AsyncTimeout::attachEventBase(
116 EventBase* eventBase,
117 InternalEnum internal) {
118 attachTimeoutManager(eventBase, internal);
121 void AsyncTimeout::detachTimeoutManager() {
122 // Only allow the event base to be changed if the timeout is not
123 // currently installed.
125 // Programmer bug. Abort the program.
126 LOG(ERROR) << "detachEventBase() called on scheduled timeout; aborting";
131 if (timeoutManager_) {
132 timeoutManager_->detachTimeoutManager(this);
133 timeoutManager_ = nullptr;
137 void AsyncTimeout::detachEventBase() {
138 detachTimeoutManager();
141 void AsyncTimeout::libeventCallback(int fd, short events, void* arg) {
142 AsyncTimeout* timeout = reinterpret_cast<AsyncTimeout*>(arg);
144 assert(events == EV_TIMEOUT);
145 // prevent unused variable warnings
149 // double check that ev_flags gets reset when the timeout is not running
150 assert((event_ref_flags(&timeout->event_) & ~EVLIST_INTERNAL) == EVLIST_INIT);
152 // this can't possibly fire if timeout->eventBase_ is nullptr
153 (void) timeout->timeoutManager_->bumpHandlingTime();
156 RequestContext::setContext(timeout->context_);
158 timeout->timeoutExpired();
160 RequestContext::setContext(old_ctx);