Fix licenses
[folly.git] / folly / io / async / AsyncTimeout.cpp
1 /*
2  * Copyright 2014 Facebook, Inc.
3  *
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
11  *
12  *   http://www.apache.org/licenses/LICENSE-2.0
13  *
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
19  * under the License.
20  */
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>
25
26 #include <assert.h>
27 #include <glog/logging.h>
28
29 namespace folly {
30
31 AsyncTimeout::AsyncTimeout(TimeoutManager* timeoutManager)
32     : timeoutManager_(timeoutManager) {
33
34   event_set(&event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
35   event_.ev_base = nullptr;
36   timeoutManager_->attachTimeoutManager(
37       this,
38       TimeoutManager::InternalEnum::NORMAL);
39   RequestContext::getStaticContext();
40 }
41
42 AsyncTimeout::AsyncTimeout(EventBase* eventBase)
43     : timeoutManager_(eventBase) {
44
45   event_set(&event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
46   event_.ev_base = nullptr;
47   timeoutManager_->attachTimeoutManager(
48       this,
49       TimeoutManager::InternalEnum::NORMAL);
50   RequestContext::getStaticContext();
51 }
52
53 AsyncTimeout::AsyncTimeout(TimeoutManager* timeoutManager,
54                              InternalEnum internal)
55     : timeoutManager_(timeoutManager) {
56
57   event_set(&event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
58   event_.ev_base = nullptr;
59   timeoutManager_->attachTimeoutManager(this, internal);
60   RequestContext::getStaticContext();
61 }
62
63 AsyncTimeout::AsyncTimeout(EventBase* eventBase, InternalEnum internal)
64     : timeoutManager_(eventBase) {
65
66   event_set(&event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
67   event_.ev_base = nullptr;
68   timeoutManager_->attachTimeoutManager(this, internal);
69   RequestContext::getStaticContext();
70 }
71
72 AsyncTimeout::AsyncTimeout(): timeoutManager_(nullptr) {
73   event_set(&event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
74   event_.ev_base = nullptr;
75   RequestContext::getStaticContext();
76 }
77
78 AsyncTimeout::~AsyncTimeout() {
79   cancelTimeout();
80 }
81
82 bool AsyncTimeout::scheduleTimeout(std::chrono::milliseconds timeout) {
83   assert(timeoutManager_ != nullptr);
84   context_ = RequestContext::saveContext();
85   return timeoutManager_->scheduleTimeout(this, timeout);
86 }
87
88 bool AsyncTimeout::scheduleTimeout(uint32_t milliseconds) {
89   return scheduleTimeout(std::chrono::milliseconds(milliseconds));
90 }
91
92 void AsyncTimeout::cancelTimeout() {
93   if (isScheduled()) {
94     timeoutManager_->cancelTimeout(this);
95   }
96 }
97
98 bool AsyncTimeout::isScheduled() const {
99   return EventUtil::isEventRegistered(&event_);
100 }
101
102 void AsyncTimeout::attachTimeoutManager(
103     TimeoutManager* timeoutManager,
104     InternalEnum internal) {
105   // This also implies no timeout is scheduled.
106   assert(timeoutManager_ == nullptr);
107   assert(timeoutManager->isInTimeoutManagerThread());
108   timeoutManager_ = timeoutManager;
109
110   timeoutManager_->attachTimeoutManager(this, internal);
111 }
112
113 void AsyncTimeout::attachEventBase(
114     EventBase* eventBase,
115     InternalEnum internal) {
116   attachTimeoutManager(eventBase, internal);
117 }
118
119 void AsyncTimeout::detachTimeoutManager() {
120   // Only allow the event base to be changed if the timeout is not
121   // currently installed.
122   if (isScheduled()) {
123     // Programmer bug.  Abort the program.
124     LOG(ERROR) << "detachEventBase() called on scheduled timeout; aborting";
125     abort();
126     return;
127   }
128
129   if (timeoutManager_) {
130     timeoutManager_->detachTimeoutManager(this);
131     timeoutManager_ = nullptr;
132   }
133 }
134
135 void AsyncTimeout::detachEventBase() {
136   detachTimeoutManager();
137 }
138
139 void AsyncTimeout::libeventCallback(int fd, short events, void* arg) {
140   AsyncTimeout* timeout = reinterpret_cast<AsyncTimeout*>(arg);
141   assert(fd == -1);
142   assert(events == EV_TIMEOUT);
143
144   // double check that ev_flags gets reset when the timeout is not running
145   assert((timeout->event_.ev_flags & ~EVLIST_INTERNAL) == EVLIST_INIT);
146
147   // this can't possibly fire if timeout->eventBase_ is nullptr
148   (void) timeout->timeoutManager_->bumpHandlingTime();
149
150   auto old_ctx =
151     RequestContext::setContext(timeout->context_);
152
153   timeout->timeoutExpired();
154
155   RequestContext::setContext(old_ctx);
156 }
157
158 } // folly