diff options
author | Hidehiko Abe <hidehiko@google.com> | 2017-12-13 19:00:02 +0900 |
---|---|---|
committer | Hidehiko Abe <hidehiko@google.com> | 2017-12-13 23:42:13 +0900 |
commit | 0411add1e14cc2dc041f5f1776f05a8c4b787d73 (patch) | |
tree | 19a081baf4afcba8d442b5e839cb1ff247f31b7f /mojo/public/cpp/bindings/struct_ptr.h | |
parent | c96e5aa6f5f1f6df03ef539b4b85c78bf7c292e5 (diff) | |
download | libmojo-0411add1e14cc2dc041f5f1776f05a8c4b787d73.tar.gz |
Revert "Revert "libmojo: Uprev the library to r456626 from Chromium""
This reverts commit 21a249e4d9cb0b2ec6f0ff84ed5f7939ea67ac52.
Test: Build.
Change-Id: Id31199817067e933eb08889b21b83c787b0d4c0d
Merged-In: I2f77e0bb4541d6520dac974cd499b30561c6658f
Diffstat (limited to 'mojo/public/cpp/bindings/struct_ptr.h')
-rw-r--r-- | mojo/public/cpp/bindings/struct_ptr.h | 203 |
1 files changed, 138 insertions, 65 deletions
diff --git a/mojo/public/cpp/bindings/struct_ptr.h b/mojo/public/cpp/bindings/struct_ptr.h index 92f2728..b135312 100644 --- a/mojo/public/cpp/bindings/struct_ptr.h +++ b/mojo/public/cpp/bindings/struct_ptr.h @@ -5,23 +5,26 @@ #ifndef MOJO_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_ #define MOJO_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_ +#include <functional> +#include <memory> #include <new> #include "base/logging.h" #include "base/macros.h" +#include "base/optional.h" +#include "mojo/public/cpp/bindings/lib/hash_util.h" #include "mojo/public/cpp/bindings/type_converter.h" namespace mojo { namespace internal { +constexpr size_t kHashSeed = 31; + template <typename Struct> -class StructHelper { - public: - template <typename Ptr> - static void Initialize(Ptr* ptr) { - ptr->Initialize(); - } -}; +class StructPtrWTFHelper; + +template <typename Struct> +class InlinedStructPtrWTFHelper; } // namespace internal @@ -31,35 +34,34 @@ class StructPtr { public: using Struct = S; - StructPtr() : ptr_(nullptr) {} - StructPtr(decltype(nullptr)) : ptr_(nullptr) {} + StructPtr() = default; + StructPtr(decltype(nullptr)) {} - ~StructPtr() { delete ptr_; } + ~StructPtr() = default; StructPtr& operator=(decltype(nullptr)) { reset(); return *this; } - StructPtr(StructPtr&& other) : ptr_(nullptr) { Take(&other); } + StructPtr(StructPtr&& other) { Take(&other); } StructPtr& operator=(StructPtr&& other) { Take(&other); return *this; } + template <typename... Args> + StructPtr(base::in_place_t, Args&&... args) + : ptr_(new Struct(std::forward<Args>(args)...)) {} + template <typename U> U To() const { return TypeConverter<U, StructPtr>::Convert(*this); } - void reset() { - if (ptr_) { - delete ptr_; - ptr_ = nullptr; - } - } + void reset() { ptr_.reset(); } - bool is_null() const { return ptr_ == nullptr; } + bool is_null() const { return !ptr_; } Struct& operator*() const { DCHECK(ptr_); @@ -67,9 +69,9 @@ class StructPtr { } Struct* operator->() const { DCHECK(ptr_); - return ptr_; + return ptr_.get(); } - Struct* get() const { return ptr_; } + Struct* get() const { return ptr_.get(); } void Swap(StructPtr* other) { std::swap(ptr_, other->ptr_); } @@ -78,52 +80,52 @@ class StructPtr { // that it contains Mojo handles). StructPtr Clone() const { return is_null() ? StructPtr() : ptr_->Clone(); } + // Compares the pointees (which might both be null). + // TODO(tibell): Get rid of Equals in favor of the operator. Same for Hash. bool Equals(const StructPtr& other) const { if (is_null() || other.is_null()) return is_null() && other.is_null(); return ptr_->Equals(*other.ptr_); } - private: - // TODO(dcheng): Use an explicit conversion operator. - typedef Struct* StructPtr::*Testable; + // Hashes based on the pointee (which might be null). + size_t Hash(size_t seed) const { + if (is_null()) + return internal::HashCombine(seed, 0); + return ptr_->Hash(seed); + } - public: - operator Testable() const { return ptr_ ? &StructPtr::ptr_ : 0; } + explicit operator bool() const { return !is_null(); } private: - friend class internal::StructHelper<Struct>; - - // Forbid the == and != operators explicitly, otherwise StructPtr will be - // converted to Testable to do == or != comparison. - template <typename T> - bool operator==(const StructPtr<T>& other) const = delete; - template <typename T> - bool operator!=(const StructPtr<T>& other) const = delete; - - void Initialize() { - DCHECK(!ptr_); - ptr_ = new Struct(); - } - + friend class internal::StructPtrWTFHelper<Struct>; void Take(StructPtr* other) { reset(); Swap(other); } - Struct* ptr_; + std::unique_ptr<Struct> ptr_; DISALLOW_COPY_AND_ASSIGN(StructPtr); }; +template <typename T> +bool operator==(const StructPtr<T>& lhs, const StructPtr<T>& rhs) { + return lhs.Equals(rhs); +} +template <typename T> +bool operator!=(const StructPtr<T>& lhs, const StructPtr<T>& rhs) { + return !(lhs == rhs); +} + // Designed to be used when Struct is small and copyable. template <typename S> class InlinedStructPtr { public: using Struct = S; - InlinedStructPtr() : is_null_(true) {} - InlinedStructPtr(decltype(nullptr)) : is_null_(true) {} + InlinedStructPtr() : state_(NIL) {} + InlinedStructPtr(decltype(nullptr)) : state_(NIL) {} ~InlinedStructPtr() {} @@ -132,79 +134,150 @@ class InlinedStructPtr { return *this; } - InlinedStructPtr(InlinedStructPtr&& other) : is_null_(true) { Take(&other); } + InlinedStructPtr(InlinedStructPtr&& other) : state_(NIL) { Take(&other); } InlinedStructPtr& operator=(InlinedStructPtr&& other) { Take(&other); return *this; } + template <typename... Args> + InlinedStructPtr(base::in_place_t, Args&&... args) + : value_(std::forward<Args>(args)...), state_(VALID) {} + template <typename U> U To() const { return TypeConverter<U, InlinedStructPtr>::Convert(*this); } void reset() { - is_null_ = true; + state_ = NIL; value_. ~Struct(); new (&value_) Struct(); } - bool is_null() const { return is_null_; } + bool is_null() const { return state_ == NIL; } Struct& operator*() const { - DCHECK(!is_null_); + DCHECK(state_ == VALID); return value_; } Struct* operator->() const { - DCHECK(!is_null_); + DCHECK(state_ == VALID); return &value_; } Struct* get() const { return &value_; } void Swap(InlinedStructPtr* other) { std::swap(value_, other->value_); - std::swap(is_null_, other->is_null_); + std::swap(state_, other->state_); } InlinedStructPtr Clone() const { return is_null() ? InlinedStructPtr() : value_.Clone(); } + + // Compares the pointees (which might both be null). bool Equals(const InlinedStructPtr& other) const { if (is_null() || other.is_null()) return is_null() && other.is_null(); return value_.Equals(other.value_); } - private: - // TODO(dcheng): Use an explicit conversion operator. - typedef Struct InlinedStructPtr::*Testable; + // Hashes based on the pointee (which might be null). + size_t Hash(size_t seed) const { + if (is_null()) + return internal::HashCombine(seed, 0); + return value_.Hash(seed); + } - public: - operator Testable() const { return is_null_ ? 0 : &InlinedStructPtr::value_; } + explicit operator bool() const { return !is_null(); } private: - friend class internal::StructHelper<Struct>; - - // Forbid the == and != operators explicitly, otherwise InlinedStructPtr will - // be converted to Testable to do == or != comparison. - template <typename T> - bool operator==(const InlinedStructPtr<T>& other) const = delete; - template <typename T> - bool operator!=(const InlinedStructPtr<T>& other) const = delete; - - void Initialize() { is_null_ = false; } - + friend class internal::InlinedStructPtrWTFHelper<Struct>; void Take(InlinedStructPtr* other) { reset(); Swap(other); } + enum State { + VALID, + NIL, + DELETED, // For use in WTF::HashMap only + }; + mutable Struct value_; - bool is_null_; + State state_; DISALLOW_COPY_AND_ASSIGN(InlinedStructPtr); }; +template <typename T> +bool operator==(const InlinedStructPtr<T>& lhs, + const InlinedStructPtr<T>& rhs) { + return lhs.Equals(rhs); +} +template <typename T> +bool operator!=(const InlinedStructPtr<T>& lhs, + const InlinedStructPtr<T>& rhs) { + return !(lhs == rhs); +} + +namespace internal { + +template <typename Struct> +class StructPtrWTFHelper { + public: + static bool IsHashTableDeletedValue(const StructPtr<Struct>& value) { + return value.ptr_.get() == reinterpret_cast<Struct*>(1u); + } + + static void ConstructDeletedValue(mojo::StructPtr<Struct>& slot) { + // |slot| refers to a previous, real value that got deleted and had its + // destructor run, so this is the first time the "deleted value" has its + // constructor called. + // + // Dirty trick: implant an invalid pointer in |ptr_|. Destructor isn't + // called for deleted buckets, so this is okay. + new (&slot) StructPtr<Struct>(); + slot.ptr_.reset(reinterpret_cast<Struct*>(1u)); + } +}; + +template <typename Struct> +class InlinedStructPtrWTFHelper { + public: + static bool IsHashTableDeletedValue(const InlinedStructPtr<Struct>& value) { + return value.state_ == InlinedStructPtr<Struct>::DELETED; + } + + static void ConstructDeletedValue(mojo::InlinedStructPtr<Struct>& slot) { + // |slot| refers to a previous, real value that got deleted and had its + // destructor run, so this is the first time the "deleted value" has its + // constructor called. + new (&slot) InlinedStructPtr<Struct>(); + slot.state_ = InlinedStructPtr<Struct>::DELETED; + } +}; + +} // namespace internal } // namespace mojo +namespace std { + +template <typename T> +struct hash<mojo::StructPtr<T>> { + size_t operator()(const mojo::StructPtr<T>& value) const { + return value.Hash(mojo::internal::kHashSeed); + } +}; + +template <typename T> +struct hash<mojo::InlinedStructPtr<T>> { + size_t operator()(const mojo::InlinedStructPtr<T>& value) const { + return value.Hash(mojo::internal::kHashSeed); + } +}; + +} // namespace std + #endif // MOJO_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_ |