UnboundedBlockingQueue: Adjust segment size
[folly.git] / folly / Try-inl.h
1 /*
2  * Copyright 2017 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/Utility.h>
20
21 #include <stdexcept>
22 #include <tuple>
23
24 namespace folly {
25
26 template <class T>
27 Try<T>::Try(Try<T>&& t) noexcept : contains_(t.contains_) {
28   if (contains_ == Contains::VALUE) {
29     new (&value_)T(std::move(t.value_));
30   } else if (contains_ == Contains::EXCEPTION) {
31     new (&e_) exception_wrapper(std::move(t.e_));
32   }
33 }
34
35 template <class T>
36 template <class T2>
37 Try<T>::Try(typename std::enable_if<std::is_same<Unit, T2>::value,
38                                     Try<void> const&>::type t)
39     : contains_(Contains::NOTHING) {
40   if (t.hasValue()) {
41     contains_ = Contains::VALUE;
42     new (&value_) T();
43   } else if (t.hasException()) {
44     contains_ = Contains::EXCEPTION;
45     new (&e_) exception_wrapper(t.exception());
46   }
47 }
48
49 template <class T>
50 Try<T>& Try<T>::operator=(Try<T>&& t) noexcept {
51   if (this == &t) {
52     return *this;
53   }
54
55   this->~Try();
56   contains_ = t.contains_;
57   if (contains_ == Contains::VALUE) {
58     new (&value_)T(std::move(t.value_));
59   } else if (contains_ == Contains::EXCEPTION) {
60     new (&e_) exception_wrapper(std::move(t.e_));
61   }
62   return *this;
63 }
64
65 template <class T>
66 Try<T>::Try(const Try<T>& t) {
67   static_assert(
68       std::is_copy_constructible<T>::value,
69       "T must be copyable for Try<T> to be copyable");
70   contains_ = t.contains_;
71   if (contains_ == Contains::VALUE) {
72     new (&value_)T(t.value_);
73   } else if (contains_ == Contains::EXCEPTION) {
74     new (&e_) 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_) exception_wrapper(t.e_);
89   }
90   return *this;
91 }
92
93 template <class T>
94 Try<T>::~Try() {
95   if (LIKELY(contains_ == Contains::VALUE)) {
96     value_.~T();
97   } else if (UNLIKELY(contains_ == Contains::EXCEPTION)) {
98     e_.~exception_wrapper();
99   }
100 }
101
102 template <class T>
103 T& Try<T>::value() & {
104   throwIfFailed();
105   return value_;
106 }
107
108 template <class T>
109 T&& Try<T>::value() && {
110   throwIfFailed();
111   return std::move(value_);
112 }
113
114 template <class T>
115 const T& Try<T>::value() const & {
116   throwIfFailed();
117   return value_;
118 }
119
120 template <class T>
121 const T&& Try<T>::value() const && {
122   throwIfFailed();
123   return std::move(value_);
124 }
125
126 template <class T>
127 void Try<T>::throwIfFailed() const {
128   switch (contains_) {
129     case Contains::VALUE:
130       return;
131     case Contains::EXCEPTION:
132       e_.throw_exception();
133     default:
134       try_detail::throwUsingUninitializedTry();
135   }
136 }
137
138 void Try<void>::throwIfFailed() const {
139   if (!hasValue_) {
140     e_.throw_exception();
141   }
142 }
143
144 template <typename F>
145 typename std::enable_if<
146   !std::is_same<typename std::result_of<F()>::type, void>::value,
147   Try<typename std::result_of<F()>::type>>::type
148 makeTryWith(F&& f) {
149   typedef typename std::result_of<F()>::type ResultType;
150   try {
151     return Try<ResultType>(f());
152   } catch (std::exception& e) {
153     return Try<ResultType>(exception_wrapper(std::current_exception(), e));
154   } catch (...) {
155     return Try<ResultType>(exception_wrapper(std::current_exception()));
156   }
157 }
158
159 template <typename F>
160 typename std::enable_if<
161   std::is_same<typename std::result_of<F()>::type, void>::value,
162   Try<void>>::type
163 makeTryWith(F&& f) {
164   try {
165     f();
166     return Try<void>();
167   } catch (std::exception& e) {
168     return Try<void>(exception_wrapper(std::current_exception(), e));
169   } catch (...) {
170     return Try<void>(exception_wrapper(std::current_exception()));
171   }
172 }
173
174 namespace try_detail {
175
176 /**
177  * Trait that removes the layer of Try abstractions from the passed in type
178  */
179 template <typename Type>
180 struct RemoveTry;
181 template <template <typename...> class TupleType, typename... Types>
182 struct RemoveTry<TupleType<folly::Try<Types>...>> {
183   using type = TupleType<Types...>;
184 };
185
186 template <std::size_t... Indices, typename Tuple>
187 auto unwrapTryTupleImpl(folly::index_sequence<Indices...>, Tuple&& instance) {
188   using std::get;
189   using ReturnType = typename RemoveTry<typename std::decay<Tuple>::type>::type;
190   return ReturnType{(get<Indices>(std::forward<Tuple>(instance)).value())...};
191 }
192 } // namespace try_detail
193
194 template <typename Tuple>
195 auto unwrapTryTuple(Tuple&& instance) {
196   using TupleDecayed = typename std::decay<Tuple>::type;
197   using Seq = folly::make_index_sequence<std::tuple_size<TupleDecayed>::value>;
198   return try_detail::unwrapTryTupleImpl(Seq{}, std::forward<Tuple>(instance));
199 }
200
201 } // namespace folly