Line data Source code
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>
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 0 : 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.
92 0 : Optional() : has_value_(false), empty_('\0') {
93 0 : PoisonValue();
94 0 : }
95 :
96 : // Construct an Optional that contains a value.
97 0 : explicit Optional(const T& value) : has_value_(true) {
98 0 : new (&value_) T(value);
99 0 : }
100 0 : explicit Optional(T&& value) : has_value_(true) {
101 0 : new (&value_) T(std::move(value));
102 0 : }
103 :
104 : // Copy constructor: copies the value from m if it has one.
105 0 : Optional(const Optional& m) : has_value_(m.has_value_) {
106 0 : if (has_value_)
107 0 : new (&value_) T(m.value_);
108 : else
109 0 : PoisonValue();
110 0 : }
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).
116 0 : Optional(Optional&& m) : has_value_(m.has_value_) {
117 0 : if (has_value_)
118 0 : new (&value_) T(std::move(m.value_));
119 : else
120 0 : PoisonValue();
121 0 : }
122 :
123 0 : ~Optional() {
124 0 : if (has_value_)
125 0 : value_.~T();
126 : else
127 0 : UnpoisonValue();
128 0 : }
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 0 : Optional& operator=(const Optional& m) {
133 0 : if (m.has_value_) {
134 0 : if (has_value_) {
135 0 : value_ = m.value_; // T's copy assignment.
136 : } else {
137 0 : UnpoisonValue();
138 0 : new (&value_) T(m.value_); // T's copy constructor.
139 0 : has_value_ = true;
140 : }
141 : } else {
142 0 : reset();
143 : }
144 0 : 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 0 : Optional& operator=(Optional&& m) {
151 0 : if (m.has_value_) {
152 0 : if (has_value_) {
153 0 : value_ = std::move(m.value_); // T's move assignment.
154 : } else {
155 0 : UnpoisonValue();
156 0 : new (&value_) T(std::move(m.value_)); // T's move constructor.
157 0 : has_value_ = true;
158 : }
159 : } else {
160 0 : reset();
161 : }
162 0 : 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.
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.
194 0 : void reset() {
195 0 : if (!has_value_)
196 0 : return;
197 0 : value_.~T();
198 0 : has_value_ = false;
199 0 : PoisonValue();
200 : }
201 :
202 : template <class... Args>
203 0 : void emplace(Args&&... args) {
204 0 : if (has_value_)
205 0 : value_.~T();
206 : else
207 0 : UnpoisonValue();
208 0 : new (&value_) T(std::forward<Args>(args)...);
209 0 : has_value_ = true;
210 0 : }
211 :
212 : // Conversion to bool to test if we have a value.
213 0 : explicit operator bool() const { return has_value_; }
214 :
215 : // Dereferencing. Only allowed if we have a value.
216 0 : const T* operator->() const {
217 0 : RTC_DCHECK(has_value_);
218 0 : return &value_;
219 : }
220 0 : T* operator->() {
221 0 : RTC_DCHECK(has_value_);
222 0 : return &value_;
223 : }
224 0 : const T& operator*() const {
225 0 : RTC_DCHECK(has_value_);
226 0 : return value_;
227 : }
228 0 : T& operator*() {
229 0 : RTC_DCHECK(has_value_);
230 0 : return value_;
231 : }
232 :
233 : // Dereference with a default value in case we don't have a value.
234 0 : 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 0 : return has_value_ ? *optional_internal::FunctionThatDoesNothing(&value_)
239 0 : : 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 0 : friend bool operator==(const T& value, const Optional& opt) {
252 0 : return opt.has_value_ && value == opt.value_;
253 : }
254 :
255 0 : friend bool operator!=(const Optional& m1, const Optional& m2) {
256 0 : return m1.has_value_ && m2.has_value_ ? m1.value_ != m2.value_
257 0 : : 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.
268 0 : void PoisonValue() {
269 0 : rtc::AsanPoison(rtc::MakeArrayView(&value_, 1));
270 0 : rtc::MsanMarkUninitialized(rtc::MakeArrayView(&value_, 1));
271 0 : }
272 :
273 : // Tell sanitizers that value_ is OK to touch again.
274 0 : void UnpoisonValue() {
275 0 : rtc::AsanUnpoison(rtc::MakeArrayView(&value_, 1));
276 0 : }
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_
|