unioil-loyalty-rn-app/ios/Pods/Flipper-Folly/folly/fibers/Promise-inl.h

119 lines
3.2 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/fibers/Baton.h>
namespace folly {
namespace fibers {
template <class T, class BatonT>
Promise<T, BatonT>::Promise(folly::Try<T>& value, BatonT& baton)
: value_(&value), baton_(&baton) {}
template <class T, class BatonT>
Promise<T, BatonT>::Promise(Promise&& other) noexcept
: value_(other.value_), baton_(other.baton_) {
other.value_ = nullptr;
other.baton_ = nullptr;
}
template <class T, class BatonT>
Promise<T, BatonT>& Promise<T, BatonT>::operator=(Promise&& other) {
std::swap(value_, other.value_);
std::swap(baton_, other.baton_);
return *this;
}
template <class T, class BatonT>
void Promise<T, BatonT>::throwIfFulfilled() const {
if (!value_) {
throw std::logic_error("promise already fulfilled");
}
}
template <class T, class BatonT>
Promise<T, BatonT>::~Promise() {
if (value_) {
setException(folly::make_exception_wrapper<std::logic_error>(
"promise not fulfilled"));
}
}
template <class T, class BatonT>
void Promise<T, BatonT>::setException(folly::exception_wrapper e) {
setTry(folly::Try<T>(e));
}
template <class T, class BatonT>
void Promise<T, BatonT>::setTry(folly::Try<T>&& t) {
throwIfFulfilled();
*value_ = std::move(t);
value_ = nullptr;
// Baton::post has to be the last step here, since if Promise is not owned by
// the posting thread, it may be destroyed right after Baton::post is called.
baton_->post();
}
template <class T, class BatonT>
template <class M>
void Promise<T, BatonT>::setValue(M&& v) {
static_assert(!std::is_same<T, void>::value, "Use setValue() instead");
setTry(folly::Try<T>(std::forward<M>(v)));
}
template <class T, class BatonT>
void Promise<T, BatonT>::setValue() {
static_assert(std::is_same<T, void>::value, "Use setValue(value) instead");
setTry(folly::Try<void>());
}
template <class T, class BatonT>
template <class F>
void Promise<T, BatonT>::setWith(F&& func) {
setTry(makeTryWith(std::forward<F>(func)));
}
template <class T, class BatonT>
template <class F>
typename Promise<T, BatonT>::value_type Promise<T, BatonT>::await_async(
F&& func) {
folly::Try<value_type> result;
std::exception_ptr funcException;
BatonT baton;
baton.wait([&func, &result, &baton, &funcException]() mutable {
try {
func(Promise<value_type, BatonT>(result, baton));
} catch (...) {
// Save the exception, but still wait for baton to be posted by user code
// or promise destructor.
funcException = std::current_exception();
}
});
if (UNLIKELY(funcException != nullptr)) {
std::rethrow_exception(funcException);
}
return std::move(result).value();
}
} // namespace fibers
} // namespace folly