Fix SimpleBarrier
[folly.git] / folly / Try-inl.h
1 /*
2  * Copyright 2016 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 <folly/detail/TryDetail.h>
20 #include <stdexcept>
21
22 namespace folly {
23
24 template <class T>
25 Try<T>::Try(Try<T>&& t) noexcept : contains_(t.contains_) {
26   if (contains_ == Contains::VALUE) {
27     new (&value_)T(std::move(t.value_));
28   } else if (contains_ == Contains::EXCEPTION) {
29     new (&e_)std::unique_ptr<exception_wrapper>(std::move(t.e_));
30   }
31 }
32
33 template <class T>
34 template <class T2>
35 Try<T>::Try(typename std::enable_if<std::is_same<Unit, T2>::value,
36                                     Try<void> const&>::type t)
37     : contains_(Contains::NOTHING) {
38   if (t.hasValue()) {
39     contains_ = Contains::VALUE;
40     new (&value_) T();
41   } else if (t.hasException()) {
42     contains_ = Contains::EXCEPTION;
43     new (&e_) std::unique_ptr<exception_wrapper>(
44         folly::make_unique<exception_wrapper>(t.exception()));
45   }
46 }
47
48 template <class T>
49 Try<T>& Try<T>::operator=(Try<T>&& t) noexcept {
50   if (this == &t) {
51     return *this;
52   }
53
54   this->~Try();
55   contains_ = t.contains_;
56   if (contains_ == Contains::VALUE) {
57     new (&value_)T(std::move(t.value_));
58   } else if (contains_ == Contains::EXCEPTION) {
59     new (&e_)std::unique_ptr<exception_wrapper>(std::move(t.e_));
60   }
61   return *this;
62 }
63
64 template <class T>
65 Try<T>::Try(const Try<T>& t) {
66   static_assert(
67       std::is_copy_constructible<T>::value,
68       "T must be copyable for Try<T> to be copyable");
69   contains_ = t.contains_;
70   if (contains_ == Contains::VALUE) {
71     new (&value_)T(t.value_);
72   } else if (contains_ == Contains::EXCEPTION) {
73     new (&e_)std::unique_ptr<exception_wrapper>();
74     e_ = folly::make_unique<exception_wrapper>(*(t.e_));
75   }
76 }
77
78 template <class T>
79 Try<T>& Try<T>::operator=(const Try<T>& t) {
80   static_assert(
81       std::is_copy_constructible<T>::value,
82       "T must be copyable for Try<T> to be copyable");
83   this->~Try();
84   contains_ = t.contains_;
85   if (contains_ == Contains::VALUE) {
86     new (&value_)T(t.value_);
87   } else if (contains_ == Contains::EXCEPTION) {
88     new (&e_)std::unique_ptr<exception_wrapper>();
89     e_ = folly::make_unique<exception_wrapper>(*(t.e_));
90   }
91   return *this;
92 }
93
94 template <class T>
95 Try<T>::~Try() {
96   if (LIKELY(contains_ == Contains::VALUE)) {
97     value_.~T();
98   } else if (UNLIKELY(contains_ == Contains::EXCEPTION)) {
99     e_.~unique_ptr<exception_wrapper>();
100   }
101 }
102
103 template <class T>
104 T& Try<T>::value() & {
105   throwIfFailed();
106   return value_;
107 }
108
109 template <class T>
110 T&& Try<T>::value() && {
111   throwIfFailed();
112   return std::move(value_);
113 }
114
115 template <class T>
116 const T& Try<T>::value() const & {
117   throwIfFailed();
118   return value_;
119 }
120
121 template <class T>
122 void Try<T>::throwIfFailed() const {
123   if (contains_ != Contains::VALUE) {
124     if (contains_ == Contains::EXCEPTION) {
125       e_->throwException();
126     } else {
127       throw UsingUninitializedTry();
128     }
129   }
130 }
131
132 void Try<void>::throwIfFailed() const {
133   if (!hasValue_) {
134     e_->throwException();
135   }
136 }
137
138 template <typename T>
139 inline T moveFromTry(Try<T>& t) {
140   return std::move(t.value());
141 }
142
143 inline void moveFromTry(Try<void>& t) {
144   return t.value();
145 }
146
147 template <typename F>
148 typename std::enable_if<
149   !std::is_same<typename std::result_of<F()>::type, void>::value,
150   Try<typename std::result_of<F()>::type>>::type
151 makeTryWith(F&& f) {
152   typedef typename std::result_of<F()>::type ResultType;
153   try {
154     return Try<ResultType>(f());
155   } catch (std::exception& e) {
156     return Try<ResultType>(exception_wrapper(std::current_exception(), e));
157   } catch (...) {
158     return Try<ResultType>(exception_wrapper(std::current_exception()));
159   }
160 }
161
162 template <typename F>
163 typename std::enable_if<
164   std::is_same<typename std::result_of<F()>::type, void>::value,
165   Try<void>>::type
166 makeTryWith(F&& f) {
167   try {
168     f();
169     return Try<void>();
170   } catch (std::exception& e) {
171     return Try<void>(exception_wrapper(std::current_exception(), e));
172   } catch (...) {
173     return Try<void>(exception_wrapper(std::current_exception()));
174   }
175 }
176
177 template <typename... Ts>
178 std::tuple<Ts...> unwrapTryTuple(std::tuple<folly::Try<Ts>...>&& ts) {
179   return detail::TryTuple<Ts...>::unwrap(
180       std::forward<std::tuple<folly::Try<Ts>...>>(ts));
181 }
182
183 } // folly