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