2 * Copyright 2016 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 #include <folly/fibers/Baton.h>
21 template <class T, class BatonT>
22 Promise<T, BatonT>::Promise(folly::Try<T>& value, BatonT& baton)
23 : value_(&value), baton_(&baton) {}
25 template <class T, class BatonT>
26 Promise<T, BatonT>::Promise(Promise&& other) noexcept
27 : value_(other.value_), baton_(other.baton_) {
28 other.value_ = nullptr;
29 other.baton_ = nullptr;
32 template <class T, class BatonT>
33 Promise<T, BatonT>& Promise<T, BatonT>::operator=(Promise&& other) {
34 std::swap(value_, other.value_);
35 std::swap(baton_, other.baton_);
39 template <class T, class BatonT>
40 void Promise<T, BatonT>::throwIfFulfilled() const {
42 throw std::logic_error("promise already fulfilled");
46 template <class T, class BatonT>
47 Promise<T, BatonT>::~Promise() {
49 setException(folly::make_exception_wrapper<std::logic_error>(
50 "promise not fulfilled"));
54 template <class T, class BatonT>
55 void Promise<T, BatonT>::setException(folly::exception_wrapper e) {
56 setTry(folly::Try<T>(e));
59 template <class T, class BatonT>
60 void Promise<T, BatonT>::setTry(folly::Try<T>&& t) {
63 *value_ = std::move(t);
66 // Baton::post has to be the last step here, since if Promise is not owned by
67 // the posting thread, it may be destroyed right after Baton::post is called.
71 template <class T, class BatonT>
73 void Promise<T, BatonT>::setValue(M&& v) {
74 static_assert(!std::is_same<T, void>::value, "Use setValue() instead");
76 setTry(folly::Try<T>(std::forward<M>(v)));
79 template <class T, class BatonT>
80 void Promise<T, BatonT>::setValue() {
81 static_assert(std::is_same<T, void>::value, "Use setValue(value) instead");
83 setTry(folly::Try<void>());
86 template <class T, class BatonT>
88 void Promise<T, BatonT>::setWith(F&& func) {
89 setTry(makeTryWith(std::forward<F>(func)));
92 template <class T, class BatonT>
94 typename Promise<T, BatonT>::value_type Promise<T, BatonT>::await(F&& func) {
95 folly::Try<value_type> result;
96 std::exception_ptr funcException;
99 baton.wait([&func, &result, &baton, &funcException]() mutable {
101 func(Promise<value_type, BatonT>(result, baton));
103 // Save the exception, but still wait for baton to be posted by user code
104 // or promise destructor.
105 funcException = std::current_exception();
109 if (UNLIKELY(funcException != nullptr)) {
110 std::rethrow_exception(funcException);
113 return folly::moveFromTry(result);