1 // Copyright 2015-2016 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #pragma once
16 
17 #include "aemu/base/TypeTraits.h"
18 
19 #include <log/log.h>
20 
21 #include <cassert>
22 #include <initializer_list>
23 #include <new>
24 #include <type_traits>
25 #include <utility>
26 
27 #include <cstddef>
28 #include <cstdlib>
29 
30 // Optional<T> - a template class to store an optional value of type T.
31 //
32 // Usage examples:
33 //
34 // Initialization and construction:
35 //   Optional<Foo> foo;            // |foo| doesn't contain a value.
36 //   Optional<Foo> foo(Foo(10));   // |foo| contains a copy-constructed value.
37 //   Optional<Foo> foo2(foo);      // |foo2| contains a copy of |foo|'s value.
38 //   Optional<Foo> foo3(std::move(foo2));  // Guess what?
39 //
40 // Assignment:
41 //   Foo foo_value(0);
42 //   Optional<Foo> foo;   // |foo| is empty.
43 //   Optional<Foo> foo2;  // |foo2| is empty.
44 //   foo2 = foo;          // |foo2| is still empty.
45 //   foo = foo_value;     // set value of |foo| to a copy of |foo_value|
46 //   foo = std::move(foo_value);  // move |foo_value| into |foo|.
47 //   foo2 = foo;          // now |foo2| has a copy of |foo|'s value.
48 //   foo = kNullopt;      // unset |foo|, it has no value.
49 //
50 // Checking and accessing value:
51 //   if (foo) {
52 //      // |foo| has a value.
53 //      doStuff(*foo);      // |*foo| is the value inside |foo|.
54 //      foo->callMethod();  // Same as (*foo).callMethod().
55 //   } else {
56 //      // |foo| is empty.
57 //   }
58 //
59 //   foo.value()              // Same as *foo
60 //   foo.valueOr(<default>)   // Return <default> is |foo| has no value.
61 //
62 // In-place construction:
63 //
64 //   Optional<Foo> foo;   // |foo| is empty.
65 //   foo.emplace(20);     // |foo| now contains a value constructed as Foo(20)
66 //
67 //   Optional<Foo> foo(kInplace, 20);  // |foo| is initialized with a value
68 //                                     // that is constructed in-place as
69 //                                     // Foo(20).
70 //
71 //   return makeOptional<Foo>(20);     // Takes Foo constructor arguments
72 //                                     // directly.
73 //
74 // Returning values:
75 //
76 //  Optional<Foo> myFunc(...) {
77 //      if (someCondition) {
78 //          return Foo(10);      // call Optional<Foo>(Foo&) constructor.
79 //      } else {
80 //          return {};           // call Optional<Foo>() constructor, which
81 //                               // builds an empty value.
82 //      }
83 //  }
84 //
85 // Memory layout:
86 //   Optional<Foo> is equivalent to:
87 //
88 //       struct {
89 //           bool flag;
90 //           Foo value;
91 //       };
92 //
93 //  in terms of memory layout. This means it *doubles* the size of integral
94 //  types. Also:
95 //
96 //  - Optional<Foo> can be constructed from anything that constructs a Foo.
97 //
98 //  - Same with Optional<Foo>(kInplace, Args...) where Args... matches any
99 //    arguments that can be passed to a Foo constructor.
100 //
101 //  - Comparison operators are provided. Beware: an empty Optional<Foo>
102 //    is always smaller than any Foo value.
103 
104 namespace gfxstream {
105 namespace guest {
106 
107 namespace details {
108 
109 // Base classes to reduce the number of instantiations of the Optional's
110 // internal members.
111 class OptionalFlagBase {
112 public:
setConstructed(bool constructed)113     void setConstructed(bool constructed) { mConstructed = constructed; }
constructed()114     constexpr bool constructed() const { return mConstructed; }
115     constexpr operator bool() const { return constructed(); }
hasValue()116     bool hasValue() const { return constructed(); }
117 
118     constexpr OptionalFlagBase(bool constructed = false)
mConstructed(constructed)119         : mConstructed(constructed) {}
120 
121 private:
122     bool mConstructed = false;
123 };
124 
125 template <size_t Size, size_t Align>
126 class OptionalStorageBase {
127 protected:
128     using StoreT = typename std::aligned_storage<Size, Align>::type;
129     StoreT mStorage = {};
130 };
131 
132 }  // namespace details
133 
134 // A tag type for empty optional construction
135 struct NulloptT {
NulloptTNulloptT136     constexpr explicit NulloptT(int) {}
137 };
138 
139 // A tag type for inplace value construction
140 struct InplaceT {
InplaceTInplaceT141     constexpr explicit InplaceT(int) {}
142 };
143 
144 // Tag values for null optional and inplace construction
145 constexpr NulloptT kNullopt{1};
146 constexpr InplaceT kInplace{1};
147 
148 // Forward declaration for an early use
149 template <class T>
150 class Optional;
151 
152 // A type trait for checking if a type is an optional instantiation
153 // Note: if you want to refer to the template name inside the template,
154 //  you need to declare this alias outside of it - because the
155 //  class name inside of the template stands for an instantiated template
156 //  E.g, for template <T> class Foo if you say 'Foo' inside the class, it
157 //  actually means Foo<T>;
158 template <class U>
159 using is_any_optional =
160         is_template_instantiation_of<typename std::decay<U>::type, Optional>;
161 
162 template <class T>
163 class Optional
164     : private details::OptionalFlagBase,
165       private details::OptionalStorageBase<sizeof(T),
166                                            std::alignment_of<T>::value> {
167     // make sure all optionals are buddies - this is needed to implement
168     // conversion from optionals of other types
169     template <class U>
170     friend class Optional;
171 
172     template <class U>
173     using self = Optional<U>;
174 
175     using base_flag = details::OptionalFlagBase;
176     using base_storage =
177             details::OptionalStorageBase<sizeof(T),
178                                          std::alignment_of<T>::value>;
179 
180 public:
181     // std::optional will have this, so let's provide it
182     using value_type = T;
183 
184     // make sure we forbid some Optional instantiations where things may get
185     // really messy
186     static_assert(!std::is_same<typename std::decay<T>::type, NulloptT>::value,
187                   "Optional of NulloptT is not allowed");
188     static_assert(!std::is_same<typename std::decay<T>::type, InplaceT>::value,
189                   "Optional of InplaceT is not allowed");
190     static_assert(!std::is_reference<T>::value,
191                   "Optional references are not allowed: use a pointer instead");
192 
193     // constructors
Optional()194     constexpr Optional() {}
Optional(NulloptT)195     constexpr Optional(NulloptT) {}
196 
Optional(const Optional & other)197     Optional(const Optional& other) : base_flag(other.constructed()) {
198         if (this->constructed()) {
199             new (&get()) T(other.get());
200         }
201     }
Optional(Optional && other)202     Optional(Optional&& other) : base_flag(other.constructed()) {
203         if (this->constructed()) {
204             new (&get()) T(std::move(other.get()));
205         }
206     }
207 
208     // Conversion constructor from optional of similar type
209     template <class U,
210               class = enable_if_c<!is_any_optional<U>::value &&
211                                   std::is_constructible<T, U>::value>>
Optional(const Optional<U> & other)212     Optional(const Optional<U>& other) : base_flag(other.constructed()) {
213         if (this->constructed()) {
214             new (&get()) T(other.get());
215         }
216     }
217 
218     // Move-conversion constructor
219     template <class U,
220               class = enable_if_c<!is_any_optional<U>::value &&
221                                   std::is_constructible<T, U>::value>>
Optional(Optional<U> && other)222     Optional(Optional<U>&& other) : base_flag(other.constructed()) {
223         if (this->constructed()) {
224             new (&get()) T(std::move(other.get()));
225         }
226     }
227 
228     // Construction from a raw value
Optional(const T & value)229     Optional(const T& value) : base_flag(true) { new (&get()) T(value); }
230     // Move construction from a raw value
Optional(T && value)231     Optional(T&& value) : base_flag(true) { new (&get()) T(std::move(value)); }
232 
233     // Inplace construction from a list of |T|'s ctor arguments
234     template <class... Args>
Optional(InplaceT,Args &&...args)235     Optional(InplaceT, Args&&... args) : base_flag(true) {
236         new (&get()) T(std::forward<Args>(args)...);
237     }
238 
239     // Inplace construction from an initializer list passed into |T|'s ctor
240     template <class U,
241               class = enable_if<
242                       std::is_constructible<T, std::initializer_list<U>>>>
Optional(InplaceT,std::initializer_list<U> il)243     Optional(InplaceT, std::initializer_list<U> il) : base_flag(true) {
244         new (&get()) T(il);
245     }
246 
247     // direct assignment
248     Optional& operator=(const Optional& other) {
249         if (&other == this) {
250             return *this;
251         }
252 
253         if (this->constructed()) {
254             if (other.constructed()) {
255                 get() = other.get();
256             } else {
257                 destruct();
258                 this->setConstructed(false);
259             }
260         } else {
261             if (other.constructed()) {
262                 new (&get()) T(other.get());
263                 this->setConstructed(true);
264             } else {
265                 ;  // we're good
266             }
267         }
268         return *this;
269     }
270 
271     // move assignment
272     Optional& operator=(Optional&& other) {
273         if (this->constructed()) {
274             if (other.constructed()) {
275                 get() = std::move(other.get());
276             } else {
277                 destruct();
278                 this->setConstructed(false);
279             }
280         } else {
281             if (other.constructed()) {
282                 new (&get()) T(std::move(other.get()));
283                 this->setConstructed(true);
284             } else {
285                 ;  // we're good
286             }
287         }
288         return *this;
289     }
290 
291     // conversion assignment
292     template <class U,
293               class = enable_if_convertible<typename std::decay<U>::type, T>>
294     Optional& operator=(const Optional<U>& other) {
295         if (this->constructed()) {
296             if (other.constructed()) {
297                 get() = other.get();
298             } else {
299                 destruct();
300                 this->setConstructed(false);
301             }
302         } else {
303             if (other.constructed()) {
304                 new (&get()) T(other.get());
305                 this->setConstructed(true);
306             } else {
307                 ;  // we're good
308             }
309         }
310         return *this;
311     }
312 
313     // conversion move assignment
314     template <class U,
315               class = enable_if_convertible<typename std::decay<U>::type, T>>
316     Optional& operator=(Optional<U>&& other) {
317         if (this->constructed()) {
318             if (other.constructed()) {
319                 get() = std::move(other.get());
320             } else {
321                 destruct();
322                 this->setConstructed(false);
323             }
324         } else {
325             if (other.constructed()) {
326                 new (&get()) T(std::move(other.get()));
327                 this->setConstructed(true);
328             } else {
329                 ;  // we're good
330             }
331         }
332         return *this;
333     }
334 
335     // the most complicated one: forwarding constructor for anything convertible
336     // to |T|, excluding the stuff implemented above explicitly
337     template <class U,
338               class = enable_if_c<
339                       !is_any_optional<typename std::decay<U>::type>::value &&
340                       std::is_convertible<typename std::decay<U>::type,
341                                           T>::value>>
342     Optional& operator=(U&& other) {
343         if (this->constructed()) {
344             get() = std::forward<U>(other);
345         } else {
346             new (&get()) T(std::forward<U>(other));
347             this->setConstructed(true);
348         }
349         return *this;
350     }
351 
352     // Adopt value checkers from the parent
353     using base_flag::operator bool;
354     using base_flag::hasValue;
355 
value()356     T& value() {
357         if (!constructed()) {
358             ALOGE("Optional not constructed");
359             abort();
360         }
361         return get();
362     }
value()363     constexpr const T& value() const {
364         if (!constructed()) {
365             ALOGE("Optional not constructed");
366             abort();
367         }
368         return get();
369     }
370 
ptr()371     T* ptr() {
372         return this->constructed() ? &get() : nullptr;
373     }
ptr()374     constexpr const T* ptr() const {
375         return this->constructed() ? &get() : nullptr;
376     }
377 
378     // Value getter with fallback
379     template <class U = T,
380               class = enable_if_convertible<typename std::decay<U>::type, T>>
valueOr(U && defaultValue)381     constexpr T valueOr(U&& defaultValue) const {
382         return this->constructed() ? get() : std::move(defaultValue);
383     }
384 
385     // Pointer-like operators
386     T& operator*() {
387         if (!constructed()) {
388             ALOGE("Optional not constructed");
389             abort();
390         }
391         return get();
392     }
393     constexpr const T& operator*() const {
394         if (!constructed()) {
395             ALOGE("Optional not constructed");
396             abort();
397         }
398         return get();
399     }
400 
401     T* operator->() {
402         if (!constructed()) {
403             ALOGE("Optional not constructed");
404             abort();
405         }
406         return &get();
407     }
408     constexpr const T* operator->() const {
409         if (!constructed()) {
410             ALOGE("Optional not constructed");
411             abort();
412         }
413         return &get();
414     }
415 
~Optional()416     ~Optional() {
417         if (this->constructed()) {
418             destruct();
419         }
420     }
421 
clear()422     void clear() {
423         if (this->constructed()) {
424             destruct();
425             this->setConstructed(false);
426         }
427     }
428 
429     template <class U,
430               class = enable_if_convertible<typename std::decay<U>::type, T>>
reset(U && u)431     void reset(U&& u) {
432         *this = std::forward<U>(u);
433     }
434 
435     // In-place construction with possible destruction of the old value
436     template <class... Args>
emplace(Args &&...args)437     void emplace(Args&&... args) {
438         if (this->constructed()) {
439             destruct();
440         }
441         new (&get()) T(std::forward<Args>(args)...);
442         this->setConstructed(true);
443     }
444 
445     // In-place construction with possible destruction of the old value
446     // initializer-list version
447     template <class U,
448               class = enable_if<
449                       std::is_constructible<T, std::initializer_list<U>>>>
emplace(std::initializer_list<U> il)450     void emplace(std::initializer_list<U> il) {
451         if (this->constructed()) {
452             destruct();
453         }
454         new (&get()) T(il);
455         this->setConstructed(true);
456     }
457 
458 private:
459     // A helper function to convert the internal raw storage to T&
get()460     constexpr const T& get() const {
461         return *reinterpret_cast<const T*>(
462                 reinterpret_cast<const char*>(&this->mStorage));
463     }
464 
465     // Same thing, mutable
get()466     T& get() {
467         return const_cast<T&>(const_cast<const Optional*>(this)->get());
468     }
469 
470     // Shortcut for a destructor call for the stored object
destruct()471     void destruct() { get().T::~T(); }
472 };
473 
474 template <class T>
makeOptional(T && t)475 Optional<typename std::decay<T>::type> makeOptional(T&& t) {
476     return Optional<typename std::decay<T>::type>(std::forward<T>(t));
477 }
478 
479 template <class T, class... Args>
makeOptional(Args &&...args)480 Optional<typename std::decay<T>::type> makeOptional(Args&&... args) {
481     return Optional<typename std::decay<T>::type>(kInplace,
482                                                   std::forward<Args>(args)...);
483 }
484 
485 template <class T>
486 bool operator==(const Optional<T>& l, const Optional<T>& r) {
487     return l.hasValue() ? r.hasValue() && *l == *r : !r.hasValue();
488 }
489 template <class T>
490 bool operator==(const Optional<T>& l, NulloptT) {
491     return !l;
492 }
493 template <class T>
494 bool operator==(NulloptT, const Optional<T>& r) {
495     return !r;
496 }
497 template <class T>
498 bool operator==(const Optional<T>& l, const T& r) {
499     return bool(l) && *l == r;
500 }
501 template <class T>
502 bool operator==(const T& l, const Optional<T>& r) {
503     return bool(r) && l == *r;
504 }
505 
506 template <class T>
507 bool operator!=(const Optional<T>& l, const Optional<T>& r) {
508     return !(l == r);
509 }
510 template <class T>
511 bool operator!=(const Optional<T>& l, NulloptT) {
512     return bool(l);
513 }
514 template <class T>
515 bool operator!=(NulloptT, const Optional<T>& r) {
516     return bool(r);
517 }
518 template <class T>
519 bool operator!=(const Optional<T>& l, const T& r) {
520     return !l || !(*l == r);
521 }
522 template <class T>
523 bool operator!=(const T& l, const Optional<T>& r) {
524     return !r || !(l == *r);
525 }
526 
527 template <class T>
528 bool operator<(const Optional<T>& l, const Optional<T>& r) {
529     return !r ? false : (!l ? true : *l < *r);
530 }
531 template <class T>
532 bool operator<(const Optional<T>&, NulloptT) {
533     return false;
534 }
535 template <class T>
536 bool operator<(NulloptT, const Optional<T>& r) {
537     return bool(r);
538 }
539 template <class T>
540 bool operator<(const Optional<T>& l, const T& r) {
541     return !l || *l < r;
542 }
543 template <class T>
544 bool operator<(const T& l, const Optional<T>& r) {
545     return bool(r) && l < *r;
546 }
547 
548 }  // namespace base
549 }  // namespace android
550