Fix some old license headers
[folly.git] / folly / io / async / TimeoutManager.cpp
1 /*
2  * Copyright 2004-present Facebook, Inc.
3  *
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
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <folly/io/async/TimeoutManager.h>
18
19 #include <boost/intrusive/list.hpp>
20
21 #include <folly/Exception.h>
22 #include <folly/Memory.h>
23 #include <folly/io/async/AsyncTimeout.h>
24
25 #include <glog/logging.h>
26
27 namespace folly {
28
29 struct TimeoutManager::CobTimeouts {
30   // small object used as a callback arg with enough info to execute the
31   // appropriate client-provided Cob
32   class CobTimeout : public AsyncTimeout {
33    public:
34     CobTimeout(TimeoutManager* timeoutManager, Func cob, InternalEnum internal)
35         : AsyncTimeout(timeoutManager, internal), cob_(std::move(cob)) {}
36
37     void timeoutExpired() noexcept override {
38       // For now, we just swallow any exceptions that the callback threw.
39       try {
40         cob_();
41       } catch (const std::exception& ex) {
42         LOG(ERROR) << "TimeoutManager::runAfterDelay() callback threw "
43                    << typeid(ex).name() << " exception: " << ex.what();
44       } catch (...) {
45         LOG(ERROR) << "TimeoutManager::runAfterDelay() callback threw "
46                    << "non-exception type";
47       }
48
49       // The CobTimeout object was allocated on the heap by runAfterDelay(),
50       // so delete it now that the it has fired.
51       delete this;
52     }
53
54    private:
55     Func cob_;
56
57    public:
58     using ListHook = boost::intrusive::list_member_hook<
59         boost::intrusive::link_mode<boost::intrusive::auto_unlink>>;
60     ListHook hook;
61     using List = boost::intrusive::list<
62         CobTimeout,
63         boost::intrusive::member_hook<CobTimeout, ListHook, &CobTimeout::hook>,
64         boost::intrusive::constant_time_size<false>>;
65   };
66
67   CobTimeout::List list;
68 };
69
70 TimeoutManager::TimeoutManager()
71     : cobTimeouts_(std::make_unique<CobTimeouts>()) {}
72
73 void TimeoutManager::runAfterDelay(
74     Func cob,
75     uint32_t milliseconds,
76     InternalEnum internal) {
77   if (!tryRunAfterDelay(std::move(cob), milliseconds, internal)) {
78     folly::throwSystemError(
79         "error in TimeoutManager::runAfterDelay(), failed to schedule timeout");
80   }
81 }
82
83 bool TimeoutManager::tryRunAfterDelay(
84     Func cob,
85     uint32_t milliseconds,
86     InternalEnum internal) {
87   if (!cobTimeouts_) {
88     return false;
89   }
90
91   auto timeout =
92       std::make_unique<CobTimeouts::CobTimeout>(this, std::move(cob), internal);
93   if (!timeout->scheduleTimeout(milliseconds)) {
94     return false;
95   }
96   cobTimeouts_->list.push_back(*timeout.release());
97   return true;
98 }
99
100 void TimeoutManager::clearCobTimeouts() {
101   if (!cobTimeouts_) {
102     return;
103   }
104
105   // Delete any unfired callback objects, so that we don't leak memory
106   // Note that we don't fire them.
107   while (!cobTimeouts_->list.empty()) {
108     auto* timeout = &cobTimeouts_->list.front();
109     delete timeout;
110   }
111 }
112
113 TimeoutManager::~TimeoutManager() {
114   clearCobTimeouts();
115 }
116 }