Rocket.Chat.ReactNative/ios/Pods/Flipper-Folly/folly/io/async/TimeoutManager.cpp

125 lines
3.6 KiB
C++

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <folly/io/async/TimeoutManager.h>
#include <boost/intrusive/list.hpp>
#include <folly/Chrono.h>
#include <folly/Exception.h>
#include <folly/Memory.h>
#include <folly/io/async/AsyncTimeout.h>
#include <glog/logging.h>
namespace folly {
struct TimeoutManager::CobTimeouts {
// small object used as a callback arg with enough info to execute the
// appropriate client-provided Cob
class CobTimeout : public AsyncTimeout {
public:
CobTimeout(TimeoutManager* timeoutManager, Func cob, InternalEnum internal)
: AsyncTimeout(timeoutManager, internal), cob_(std::move(cob)) {}
void timeoutExpired() noexcept override {
// For now, we just swallow any exceptions that the callback threw.
try {
cob_();
} catch (const std::exception& ex) {
LOG(ERROR) << "TimeoutManager::runAfterDelay() callback threw "
<< typeid(ex).name() << " exception: " << ex.what();
} catch (...) {
LOG(ERROR) << "TimeoutManager::runAfterDelay() callback threw "
<< "non-exception type";
}
// The CobTimeout object was allocated on the heap by runAfterDelay(),
// so delete it now that the it has fired.
delete this;
}
private:
Func cob_;
public:
using ListHook = boost::intrusive::list_member_hook<
boost::intrusive::link_mode<boost::intrusive::auto_unlink>>;
ListHook hook;
using List = boost::intrusive::list<
CobTimeout,
boost::intrusive::member_hook<CobTimeout, ListHook, &CobTimeout::hook>,
boost::intrusive::constant_time_size<false>>;
};
CobTimeout::List list;
};
TimeoutManager::TimeoutManager()
: cobTimeouts_(std::make_unique<CobTimeouts>()) {}
bool TimeoutManager::scheduleTimeoutHighRes(
AsyncTimeout* obj,
timeout_type_high_res timeout) {
timeout_type timeout_ms = folly::chrono::ceil<timeout_type>(timeout);
return scheduleTimeout(obj, timeout_ms);
}
void TimeoutManager::runAfterDelay(
Func cob,
uint32_t milliseconds,
InternalEnum internal) {
if (!tryRunAfterDelay(std::move(cob), milliseconds, internal)) {
folly::throwSystemError(
"error in TimeoutManager::runAfterDelay(), failed to schedule timeout");
}
}
bool TimeoutManager::tryRunAfterDelay(
Func cob,
uint32_t milliseconds,
InternalEnum internal) {
if (!cobTimeouts_) {
return false;
}
auto timeout =
std::make_unique<CobTimeouts::CobTimeout>(this, std::move(cob), internal);
if (!timeout->scheduleTimeout(milliseconds)) {
return false;
}
cobTimeouts_->list.push_back(*timeout.release());
return true;
}
void TimeoutManager::clearCobTimeouts() {
if (!cobTimeouts_) {
return;
}
// Delete any unfired callback objects, so that we don't leak memory
// Note that we don't fire them.
while (!cobTimeouts_->list.empty()) {
auto* timeout = &cobTimeouts_->list.front();
delete timeout;
}
}
TimeoutManager::~TimeoutManager() {
clearCobTimeouts();
}
} // namespace folly