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