s/valueTry/getTry/
[folly.git] / folly / wangle / Promise-inl.h
1 /*
2  * Copyright 2014 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 #pragma once
18
19 #include <atomic>
20 #include <thread>
21
22 #include "WangleException.h"
23 #include "detail.h"
24
25 namespace folly { namespace wangle {
26
27 template <class T>
28 Promise<T>::Promise() : retrieved_(false), obj_(new detail::FutureObject<T>())
29 {}
30
31 template <class T>
32 Promise<T>::Promise(Promise<T>&& other) :
33 retrieved_(other.retrieved_), obj_(other.obj_) {
34   other.obj_ = nullptr;
35 }
36
37 template <class T>
38 Promise<T>& Promise<T>::operator=(Promise<T>&& other) {
39   std::swap(obj_, other.obj_);
40   std::swap(retrieved_, other.retrieved_);
41   return *this;
42 }
43
44 template <class T>
45 void Promise<T>::throwIfFulfilled() {
46   if (!obj_)
47     throw PromiseAlreadySatisfied();
48 }
49
50 template <class T>
51 void Promise<T>::throwIfRetrieved() {
52   if (retrieved_)
53     throw FutureAlreadyRetrieved();
54 }
55
56 template <class T>
57 Promise<T>::~Promise() {
58   if (obj_) {
59     setException(BrokenPromise());
60   }
61 }
62
63 template <class T>
64 Future<T> Promise<T>::getFuture() {
65   throwIfRetrieved();
66   throwIfFulfilled();
67   retrieved_ = true;
68   return Future<T>(obj_);
69 }
70
71 template <class T>
72 template <class E>
73 void Promise<T>::setException(E const& e) {
74   throwIfFulfilled();
75   setException(std::make_exception_ptr<E>(e));
76 }
77
78 template <class T>
79 void Promise<T>::setException(std::exception_ptr const& e) {
80   throwIfFulfilled();
81   obj_->setException(e);
82   if (!retrieved_) {
83     delete obj_;
84   }
85   obj_ = nullptr;
86 }
87
88 template <class T>
89 void Promise<T>::fulfilTry(Try<T>&& t) {
90   throwIfFulfilled();
91   obj_->fulfil(std::move(t));
92   if (!retrieved_) {
93     delete obj_;
94   }
95   obj_ = nullptr;
96 }
97
98 template <class T>
99 template <class M>
100 void Promise<T>::setValue(M&& v) {
101   static_assert(!std::is_same<T, void>::value,
102                 "Use setValue() instead");
103
104   throwIfFulfilled();
105   obj_->fulfil(Try<T>(std::forward<M>(v)));
106   if (!retrieved_) {
107     delete obj_;
108   }
109   obj_ = nullptr;
110 }
111
112 template <class T>
113 void Promise<T>::setValue() {
114   static_assert(std::is_same<T, void>::value,
115                 "Use setValue(value) instead");
116
117   throwIfFulfilled();
118   obj_->fulfil(Try<void>());
119   if (!retrieved_) {
120     delete obj_;
121   }
122   obj_ = nullptr;
123 }
124
125 template <class T>
126 template <class F>
127 void Promise<T>::fulfil(const F& func) {
128   fulfilHelper(func);
129 }
130
131 template <class T>
132 template <class F>
133 typename std::enable_if<
134   std::is_convertible<typename std::result_of<F()>::type, T>::value &&
135   !std::is_same<T, void>::value>::type
136 inline Promise<T>::fulfilHelper(const F& func) {
137   throwIfFulfilled();
138   try {
139     setValue(func());
140   } catch (...) {
141     setException(std::current_exception());
142   }
143 }
144
145 template <class T>
146 template <class F>
147 typename std::enable_if<
148   std::is_same<typename std::result_of<F()>::type, void>::value &&
149   std::is_same<T, void>::value>::type
150 inline Promise<T>::fulfilHelper(const F& func) {
151   throwIfFulfilled();
152   try {
153     func();
154     setValue();
155   } catch (...) {
156     setException(std::current_exception());
157   }
158 }
159
160 }}