diff options
author | FranklinDM <mrmineshafter17@gmail.com> | 2023-03-17 18:51:04 +0800 |
---|---|---|
committer | FranklinDM <mrmineshafter17@gmail.com> | 2023-03-17 20:29:19 +0800 |
commit | 5e6a0efb65eb9176db9ec37470c5730fd4ef5d88 (patch) | |
tree | df0085e0863c6f8926a57a56907994ef4c58a2aa /mfbt | |
parent | 0c35e43441ec35bbd0e35105c1609fd8eeba624d (diff) | |
download | uxp-5e6a0efb65eb9176db9ec37470c5730fd4ef5d88.tar.gz |
Issue #2166 - Part 2: Use alignas/alignof in MaybeOneOf
Based on https://bugzilla.mozilla.org/show_bug.cgi?id=1338374
Diffstat (limited to 'mfbt')
-rw-r--r-- | mfbt/MaybeOneOf.h | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/mfbt/MaybeOneOf.h b/mfbt/MaybeOneOf.h index ea8124772d..e4f298ec51 100644 --- a/mfbt/MaybeOneOf.h +++ b/mfbt/MaybeOneOf.h @@ -3,15 +3,20 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +/* + * A class storing one of two optional value types that supports + * in-place lazy construction. + */ + #ifndef mozilla_MaybeOneOf_h #define mozilla_MaybeOneOf_h -#include "mozilla/Alignment.h" #include "mozilla/Assertions.h" #include "mozilla/Move.h" #include "mozilla/TemplateLib.h" -#include <new> // For placement new +#include <new> // for placement new +#include <stddef.h> // for size_t namespace mozilla { @@ -23,11 +28,25 @@ namespace mozilla { * |construct<T2>()|, a T1 or T2 object will be constructed with the given * arguments and that object will be destroyed when the owning MaybeOneOf is * destroyed. + * + * Because MaybeOneOf must be aligned suitable to hold any value stored within + * it, and because |alignas| requirements don't affect platform ABI with respect + * to how parameters are laid out in memory, MaybeOneOf can't be used as the + * type of a function parameter. Pass MaybeOneOf to functions by pointer or + * reference instead. */ template<class T1, class T2> -class MaybeOneOf +class MOZ_NON_PARAM MaybeOneOf { - AlignedStorage<tl::Max<sizeof(T1), sizeof(T2)>::value> storage; + static constexpr size_t StorageAlignment = + tl::Max<alignof(T1), alignof(T2)>::value; + static constexpr size_t StorageSize = + tl::Max<sizeof(T1), sizeof(T2)>::value; + + alignas(StorageAlignment) unsigned char storage_[StorageSize]; + + void* storage() { return storage_; } + const void* storage() const { return storage_; } enum State { None, SomeT1, SomeT2 } state; template <class T, class Ignored = void> struct Type2State {}; @@ -36,14 +55,14 @@ class MaybeOneOf T& as() { MOZ_ASSERT(state == Type2State<T>::result); - return *(T*)storage.addr(); + return *static_cast<T*>(storage()); } template <class T> const T& as() const { MOZ_ASSERT(state == Type2State<T>::result); - return *(T*)storage.addr(); + return *static_cast<const T*>(storage()); } public: @@ -65,7 +84,7 @@ public: } } - MaybeOneOf &operator=(MaybeOneOf&& rhs) + MaybeOneOf& operator=(MaybeOneOf&& rhs) { MOZ_ASSERT(this != &rhs, "Self-move is prohibited"); this->~MaybeOneOf(); @@ -83,7 +102,7 @@ public: { MOZ_ASSERT(state == None); state = Type2State<T>::result; - ::new (storage.addr()) T(Forward<Args>(aArgs)...); + ::new (storage()) T(Forward<Args>(aArgs)...); } template <class T> |