diff options
Diffstat (limited to 'include/mbgl')
-rw-r--r-- | include/mbgl/style/layer.hpp | 4 | ||||
-rw-r--r-- | include/mbgl/style/source.hpp | 4 | ||||
-rw-r--r-- | include/mbgl/util/peer.hpp | 111 | ||||
-rw-r--r-- | include/mbgl/util/unique_any.hpp | 271 |
4 files changed, 115 insertions, 275 deletions
diff --git a/include/mbgl/style/layer.hpp b/include/mbgl/style/layer.hpp index 12494f5387..b5a4b63d2e 100644 --- a/include/mbgl/style/layer.hpp +++ b/include/mbgl/style/layer.hpp @@ -1,7 +1,7 @@ #pragma once #include <mbgl/util/noncopyable.hpp> -#include <mbgl/util/unique_any.hpp> +#include <mbgl/util/peer.hpp> #include <mbgl/util/immutable.hpp> #include <mbgl/style/layer_type.hpp> #include <mbgl/style/types.hpp> @@ -132,7 +132,7 @@ public: // For use in SDK bindings, which store a reference to a platform-native peer // object here, so that separately-obtained references to this object share // identical platform-native peers. - util::unique_any peer; + util::peer peer; }; } // namespace style diff --git a/include/mbgl/style/source.hpp b/include/mbgl/style/source.hpp index 2f2838ade8..dc3a8d73fb 100644 --- a/include/mbgl/style/source.hpp +++ b/include/mbgl/style/source.hpp @@ -2,7 +2,7 @@ #include <mbgl/util/noncopyable.hpp> #include <mbgl/util/optional.hpp> -#include <mbgl/util/unique_any.hpp> +#include <mbgl/util/peer.hpp> #include <mbgl/util/immutable.hpp> #include <mbgl/style/types.hpp> @@ -77,7 +77,7 @@ public: // For use in SDK bindings, which store a reference to a platform-native peer // object here, so that separately-obtained references to this object share // identical platform-native peers. - util::unique_any peer; + util::peer peer; }; } // namespace style diff --git a/include/mbgl/util/peer.hpp b/include/mbgl/util/peer.hpp new file mode 100644 index 0000000000..a4abea0e88 --- /dev/null +++ b/include/mbgl/util/peer.hpp @@ -0,0 +1,111 @@ +#pragma once + +#include <type_traits> +#include <utility> + +namespace mbgl { +namespace util { + +class peer { +public: + peer() = default; + peer(const peer&) = delete; + + peer(peer&& other) + : vtable(other.vtable) + { + if (vtable) { + vtable->move(other.storage, storage); + } + other.vtable = nullptr; + } + + template <class T> + peer(T&& value) { + using _Vt = std::decay_t<T>; + vtable = get_vtable<_Vt>(); + new (&storage) _Vt(std::forward<T>(value)); + } + + ~peer() { + reset(); + } + + peer& operator=(peer&& rhs) { + peer(std::move(rhs)).swap(*this); + return *this; + } + + void reset() { + if (vtable) { + vtable->destroy(storage); + vtable = nullptr; + } + } + + void swap(peer& rhs) { + if (this == &rhs) { + return; + } else { + peer tmp(std::move(rhs)); + rhs.vtable = vtable; + if (rhs.vtable) { + rhs.vtable->move(storage, rhs.storage); + } + vtable = tmp.vtable; + if (vtable) { + vtable->move(tmp.storage, storage); + } + } + } + + bool has_value() const { + return vtable != nullptr; + } + + template <class T> + T& get() { + return reinterpret_cast<T&>(storage); + } + + template <class T> + T&& take() { + reset(); + return std::move(get<T>()); + } + +private: + using storage_t = std::aligned_storage_t<2*sizeof(void*), alignof(void*)>; + + struct vtable { + virtual ~vtable() = default; + virtual void move(storage_t&, storage_t&) = 0; + virtual void destroy(storage_t&) = 0; + }; + + template <class T> + struct vtable_impl : public vtable { + static_assert(sizeof(T) <= sizeof(storage_t), "peer object is too big"); + + void move(storage_t& src, storage_t& dst) override { + new (&dst) T(std::move(reinterpret_cast<T&>(src))); + destroy(src); + } + + void destroy(storage_t& s) override { + reinterpret_cast<T&>(s).~T(); + } + }; + + template <class T> + static vtable* get_vtable() { + static vtable_impl<T> vtable; + return &vtable; + } + + vtable* vtable = nullptr; + storage_t storage; +}; + +} // namespace util +} // namespace mbgl diff --git a/include/mbgl/util/unique_any.hpp b/include/mbgl/util/unique_any.hpp deleted file mode 100644 index c7dc8b38ea..0000000000 --- a/include/mbgl/util/unique_any.hpp +++ /dev/null @@ -1,271 +0,0 @@ -#pragma once - -#include <typeinfo> -#include <type_traits> -#include <stdexcept> -namespace mbgl { -namespace util { - -class bad_any_cast : public std::bad_cast { -public: - const char* what() const noexcept override { - return "bad any_cast<>()"; - } -}; -/** - * A variant of `std::any` for non-copyable types. - * - * Use `unique_any` for non-copyable types (e.g. `std::unique_ptr<T>`) - * or to ensure that no copies are made of copyable types that are - * moved in. - * - * `uniqe_any` differs from `std::any` in that it does not support copy construction - * or copy assignment. It also does not require the contained type to be copy - * constructible. - * - * The `any_cast<T>()` methods work similar to `std::any_cast<T>()` except that - * non-copyable types may only be cast to references. - * - * Example usage: - * unique_any u1(3); - * auto u2 = unique_any(std::move(u1)); // u1 is moved from - * int i = any_cast<int>(u2); - * - * unique_any u2; - * u2 = std::unique_ptr<int>(new int); - * std::unique_ptr<int> iPtr = any_cast<std::unique_ptr<int>>(std::move(u2)); - * - * Inspired by linb::any (https://github.com/thelink2012/any) and the - * libc++ implementation (https://github.com/llvm-mirror/libcxx). - */ -class unique_any final -{ -public: - unique_any() = default; - - //Copy constructor (deleted) - unique_any(const unique_any& rhs) = delete; - - unique_any(unique_any&& rhs) : vtable(rhs.vtable) { - if (vtable) { - vtable->move(std::move(rhs.storage), storage); - } - rhs.vtable = nullptr; - } - - // Constructs with a direct-initilizated object of type ValueType - template <typename ValueType, - typename _Vt = std::decay_t<ValueType>, - typename = std::enable_if_t<!std::is_same<_Vt, unique_any>::value> > - unique_any(ValueType&& value) { - create(std::forward<ValueType>(value)); - } - - ~unique_any() { - reset(); - } - - unique_any& operator=(unique_any&& rhs) { - unique_any(std::move(rhs)).swap(*this); - return *this; - } - - template <class ValueType, - typename = std::enable_if_t<!std::is_same<std::decay_t<ValueType>, unique_any>::value> > - unique_any& operator=(ValueType&& rhs) { - unique_any(std::forward<ValueType>(rhs)).swap(*this); - return *this; - } - - void reset() { - if (vtable) { - vtable->destroy(storage); - vtable = nullptr; - } - } - - void swap(unique_any& rhs) { - if (this == &rhs) { - return; - } else { - unique_any tmp(std::move(rhs)); - rhs.vtable = vtable; - if (rhs.vtable) { - rhs.vtable->move(std::move(storage), rhs.storage); - } - vtable = tmp.vtable; - if (vtable) { - vtable->move(std::move(tmp.storage), storage); - } - } - } - - const std::type_info& type() const { - return !has_value()? typeid(void) : vtable->type(); - } - - bool has_value() const { - return vtable != nullptr; - } - -private: - - union Storage { - using StackStorage = std::aligned_storage_t<3*sizeof(void*), std::alignment_of<void*>::value>; - Storage() = default; - - void * dynamic { nullptr }; - StackStorage stack; - }; - - template<typename T> - struct AllocateOnStack : std::integral_constant<bool, - sizeof(T) <= sizeof(Storage::stack) - && std::alignment_of<T>::value <= std::alignment_of<Storage::StackStorage>::value - && std::is_nothrow_move_constructible<T>::value> { - }; - - struct VTable { - virtual ~VTable() = default; - virtual void move(Storage&& src, Storage& dest) = 0; - virtual void destroy(Storage&) = 0; - virtual const std::type_info& type() = 0; - }; - - template <typename ValueType> - struct VTableHeap : public VTable { - void move(Storage&& src, Storage& dest) override { - dest.dynamic = src.dynamic; - src.dynamic = nullptr; - } - - void destroy(Storage& s) override { - delete reinterpret_cast<ValueType*>(s.dynamic); - } - - const std::type_info& type() override { - return typeid(ValueType); - } - }; - - template <typename ValueType> - struct VTableStack : public VTable { - void move(Storage&& src, Storage& dest) override { - new (&dest.stack) ValueType(std::move(reinterpret_cast<ValueType&>(src.stack))); - destroy(src); - } - - void destroy(Storage& s) override { - reinterpret_cast<ValueType&>(s.stack).~ValueType(); - } - - const std::type_info& type() override { - return typeid(ValueType); - } - }; - - template <typename ValueType> - static VTable* vtableForType() { - using VTableType = std::conditional_t<AllocateOnStack<ValueType>::value, VTableStack<ValueType>, VTableHeap<ValueType> >; - static VTableType vtable; - return &vtable; - } - - template <typename ValueType, typename _Vt> - std::enable_if_t<AllocateOnStack<_Vt>::value> - createStorage(ValueType&& value) { - new (&storage.stack) _Vt(std::forward<ValueType>(value)); - } - - template <typename ValueType, typename _Vt> - std::enable_if_t<!AllocateOnStack<_Vt>::value> - createStorage(ValueType&& value) { - storage.dynamic = new _Vt(std::forward<ValueType>(value)); - } - - template <typename ValueType> - void create(ValueType&& value) { - using _Vt = std::decay_t<ValueType>; - vtable = vtableForType<_Vt>(); - createStorage<ValueType, _Vt>(std::forward<ValueType>(value)); - } - - VTable* vtable { nullptr }; - Storage storage; - -protected: - template<class ValueType> - friend const ValueType* any_cast(const unique_any* operand) ; - - template<class ValueType> - friend ValueType* any_cast(unique_any* operand) ; - - template<typename ValueType, typename _Vt = std::decay_t<ValueType> > - ValueType* cast() - { - return reinterpret_cast<ValueType *>( - AllocateOnStack<_Vt>::value ? &storage.stack : storage.dynamic); - } -}; - -template<typename ValueType> -inline const ValueType* any_cast(const unique_any* any) -{ - return any_cast<ValueType>(const_cast<unique_any *>(any)); -} - -template<typename ValueType> -inline ValueType* any_cast(unique_any* any) -{ - if(any == nullptr || any->type() != typeid(ValueType)) - return nullptr; - else - return any->cast<ValueType>(); -} - -template<typename ValueType, typename _Vt = std::decay_t<ValueType> > -inline ValueType any_cast(const unique_any& any) -{ - static_assert(std::is_constructible<ValueType, const _Vt&>::value, - "any_cast type can't construct copy of contained object"); - auto temp = any_cast<_Vt>(&any); - if (temp == nullptr) { - throw bad_any_cast(); - } - return static_cast<ValueType>(*temp); -} - -template<typename ValueType, typename _Vt = std::decay_t<ValueType> > -inline ValueType any_cast(unique_any& any) -{ - static_assert(std::is_constructible<ValueType, const _Vt&>::value, - "any_cast type can't construct copy of contained object"); - auto temp = any_cast<_Vt>(&any); - if (temp == nullptr) { - throw bad_any_cast(); - } - return static_cast<ValueType>(*temp); -} - -template<typename ValueType, typename _Vt = std::remove_cv_t<ValueType> > -inline ValueType any_cast(unique_any&& any) -{ - auto temp = any_cast<_Vt>(&any); - if (temp == nullptr) { - throw bad_any_cast(); - } - auto retValue = static_cast<ValueType>(std::move(*temp)); - any.reset(); - return std::move(retValue); -} - -} // namespace util -} // namespace mbgl - -namespace std { - -inline void swap(mbgl::util::unique_any& lhs, mbgl::util::unique_any& rhs) { - lhs.swap(rhs); -} - -} // namespace std |