1 /*
2  *  Copyright 2015 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #ifndef WEBRTC_BASE_OPTIONAL_H_
12 #define WEBRTC_BASE_OPTIONAL_H_
13 
14 #include <algorithm>
15 #include <memory>
16 #include <utility>
17 
18 #include "webrtc/base/array_view.h"
19 #include "webrtc/base/checks.h"
20 #include "webrtc/base/sanitizer.h"
21 
22 namespace rtc {
23 
24 namespace optional_internal {
25 
26 #if RTC_HAS_ASAN
27 
28 // This is a non-inlined function. The optimizer can't see inside it.
29 void* FunctionThatDoesNothingImpl(void*);
30 
31 template <typename T>
FunctionThatDoesNothing(T * x)32 inline T* FunctionThatDoesNothing(T* x) {
33   return reinterpret_cast<T*>(
34       FunctionThatDoesNothingImpl(reinterpret_cast<void*>(x)));
35 }
36 
37 #else
38 
39 template <typename T>
40 inline T* FunctionThatDoesNothing(T* x) { return x; }
41 
42 #endif
43 
44 }  // namespace optional_internal
45 
46 // Simple std::optional-wannabe. It either contains a T or not.
47 //
48 // A moved-from Optional<T> may only be destroyed, and assigned to if T allows
49 // being assigned to after having been moved from. Specifically, you may not
50 // assume that it just doesn't contain a value anymore.
51 //
52 // Examples of good places to use Optional:
53 //
54 // - As a class or struct member, when the member doesn't always have a value:
55 //     struct Prisoner {
56 //       std::string name;
57 //       Optional<int> cell_number;  // Empty if not currently incarcerated.
58 //     };
59 //
60 // - As a return value for functions that may fail to return a value on all
61 //   allowed inputs. For example, a function that searches an array might
62 //   return an Optional<size_t> (the index where it found the element, or
63 //   nothing if it didn't find it); and a function that parses numbers might
64 //   return Optional<double> (the parsed number, or nothing if parsing failed).
65 //
66 // Examples of bad places to use Optional:
67 //
68 // - As a return value for functions that may fail because of disallowed
69 //   inputs. For example, a string length function should not return
70 //   Optional<size_t> so that it can return nothing in case the caller passed
71 //   it a null pointer; the function should probably use RTC_[D]CHECK instead,
72 //   and return plain size_t.
73 //
74 // - As a return value for functions that may fail to return a value on all
75 //   allowed inputs, but need to tell the caller what went wrong. Returning
76 //   Optional<double> when parsing a single number as in the example above
77 //   might make sense, but any larger parse job is probably going to need to
78 //   tell the caller what the problem was, not just that there was one.
79 //
80 // - As a non-mutable function argument. When you want to pass a value of a
81 //   type T that can fail to be there, const T* is almost always both fastest
82 //   and cleanest. (If you're *sure* that the the caller will always already
83 //   have an Optional<T>, const Optional<T>& is slightly faster than const T*,
84 //   but this is a micro-optimization. In general, stick to const T*.)
85 //
86 // TODO(kwiberg): Get rid of this class when the standard library has
87 // std::optional (and we're allowed to use it).
88 template <typename T>
89 class Optional final {
90  public:
91   // Construct an empty Optional.
Optional()92   Optional() : has_value_(false), empty_('\0') {
93     PoisonValue();
94   }
95 
96   // Construct an Optional that contains a value.
Optional(const T & value)97   explicit Optional(const T& value) : has_value_(true) {
98     new (&value_) T(value);
99   }
Optional(T && value)100   explicit Optional(T&& value) : has_value_(true) {
101     new (&value_) T(std::move(value));
102   }
103 
104   // Copy constructor: copies the value from m if it has one.
Optional(const Optional & m)105   Optional(const Optional& m) : has_value_(m.has_value_) {
106     if (has_value_)
107       new (&value_) T(m.value_);
108     else
109       PoisonValue();
110   }
111 
112   // Move constructor: if m has a value, moves the value from m, leaving m
113   // still in a state where it has a value, but a moved-from one (the
114   // properties of which depends on T; the only general guarantee is that we
115   // can destroy m).
Optional(Optional && m)116   Optional(Optional&& m) : has_value_(m.has_value_) {
117     if (has_value_)
118       new (&value_) T(std::move(m.value_));
119     else
120       PoisonValue();
121   }
122 
~Optional()123   ~Optional() {
124     if (has_value_)
125       value_.~T();
126     else
127       UnpoisonValue();
128   }
129 
130   // Copy assignment. Uses T's copy assignment if both sides have a value, T's
131   // copy constructor if only the right-hand side has a value.
132   Optional& operator=(const Optional& m) {
133     if (m.has_value_) {
134       if (has_value_) {
135         value_ = m.value_;  // T's copy assignment.
136       } else {
137         UnpoisonValue();
138         new (&value_) T(m.value_);  // T's copy constructor.
139         has_value_ = true;
140       }
141     } else {
142       reset();
143     }
144     return *this;
145   }
146 
147   // Move assignment. Uses T's move assignment if both sides have a value, T's
148   // move constructor if only the right-hand side has a value. The state of m
149   // after it's been moved from is as for the move constructor.
150   Optional& operator=(Optional&& m) {
151     if (m.has_value_) {
152       if (has_value_) {
153         value_ = std::move(m.value_);  // T's move assignment.
154       } else {
155         UnpoisonValue();
156         new (&value_) T(std::move(m.value_));  // T's move constructor.
157         has_value_ = true;
158       }
159     } else {
160       reset();
161     }
162     return *this;
163   }
164 
165   // Swap the values if both m1 and m2 have values; move the value if only one
166   // of them has one.
swap(Optional & m1,Optional & m2)167   friend void swap(Optional& m1, Optional& m2) {
168     if (m1.has_value_) {
169       if (m2.has_value_) {
170         // Both have values: swap.
171         using std::swap;
172         swap(m1.value_, m2.value_);
173       } else {
174         // Only m1 has a value: move it to m2.
175         m2.UnpoisonValue();
176         new (&m2.value_) T(std::move(m1.value_));
177         m1.value_.~T();  // Destroy the moved-from value.
178         m1.has_value_ = false;
179         m2.has_value_ = true;
180         m1.PoisonValue();
181       }
182     } else if (m2.has_value_) {
183       // Only m2 has a value: move it to m1.
184       m1.UnpoisonValue();
185       new (&m1.value_) T(std::move(m2.value_));
186       m2.value_.~T();  // Destroy the moved-from value.
187       m1.has_value_ = true;
188       m2.has_value_ = false;
189       m2.PoisonValue();
190     }
191   }
192 
193   // Destroy any contained value. Has no effect if we have no value.
reset()194   void reset() {
195     if (!has_value_)
196       return;
197     value_.~T();
198     has_value_ = false;
199     PoisonValue();
200   }
201 
202   template <class... Args>
emplace(Args &&...args)203   void emplace(Args&&... args) {
204     if (has_value_)
205       value_.~T();
206     else
207       UnpoisonValue();
208     new (&value_) T(std::forward<Args>(args)...);
209     has_value_ = true;
210   }
211 
212   // Conversion to bool to test if we have a value.
213   explicit operator bool() const { return has_value_; }
214 
215   // Dereferencing. Only allowed if we have a value.
216   const T* operator->() const {
217     RTC_DCHECK(has_value_);
218     return &value_;
219   }
220   T* operator->() {
221     RTC_DCHECK(has_value_);
222     return &value_;
223   }
224   const T& operator*() const {
225     RTC_DCHECK(has_value_);
226     return value_;
227   }
228   T& operator*() {
229     RTC_DCHECK(has_value_);
230     return value_;
231   }
232 
233   // Dereference with a default value in case we don't have a value.
value_or(const T & default_val)234   const T& value_or(const T& default_val) const {
235     // The no-op call prevents the compiler from generating optimized code that
236     // reads value_ even if !has_value_, but only if FunctionThatDoesNothing is
237     // not completely inlined; see its declaration.).
238     return has_value_ ? *optional_internal::FunctionThatDoesNothing(&value_)
239                       : default_val;
240   }
241 
242   // Equality tests. Two Optionals are equal if they contain equivalent values,
243   // or if they're both empty.
244   friend bool operator==(const Optional& m1, const Optional& m2) {
245     return m1.has_value_ && m2.has_value_ ? m1.value_ == m2.value_
246                                           : m1.has_value_ == m2.has_value_;
247   }
248   friend bool operator==(const Optional& opt, const T& value) {
249     return opt.has_value_ && opt.value_ == value;
250   }
251   friend bool operator==(const T& value, const Optional& opt) {
252     return opt.has_value_ && value == opt.value_;
253   }
254 
255   friend bool operator!=(const Optional& m1, const Optional& m2) {
256     return m1.has_value_ && m2.has_value_ ? m1.value_ != m2.value_
257                                           : m1.has_value_ != m2.has_value_;
258   }
259   friend bool operator!=(const Optional& opt, const T& value) {
260     return !opt.has_value_ || opt.value_ != value;
261   }
262   friend bool operator!=(const T& value, const Optional& opt) {
263     return !opt.has_value_ || value != opt.value_;
264   }
265 
266  private:
267   // Tell sanitizers that value_ shouldn't be touched.
PoisonValue()268   void PoisonValue() {
269     rtc::AsanPoison(rtc::MakeArrayView(&value_, 1));
270     rtc::MsanMarkUninitialized(rtc::MakeArrayView(&value_, 1));
271   }
272 
273   // Tell sanitizers that value_ is OK to touch again.
UnpoisonValue()274   void UnpoisonValue() {
275     rtc::AsanUnpoison(rtc::MakeArrayView(&value_, 1));
276   }
277 
278   bool has_value_;  // True iff value_ contains a live value.
279   union {
280     // empty_ exists only to make it possible to initialize the union, even when
281     // it doesn't contain any data. If the union goes uninitialized, it may
282     // trigger compiler warnings.
283     char empty_;
284     // By placing value_ in a union, we get to manage its construction and
285     // destruction manually: the Optional constructors won't automatically
286     // construct it, and the Optional destructor won't automatically destroy
287     // it. Basically, this just allocates a properly sized and aligned block of
288     // memory in which we can manually put a T with placement new.
289     T value_;
290   };
291 };
292 
293 }  // namespace rtc
294 
295 #endif  // WEBRTC_BASE_OPTIONAL_H_
296