aboutsummaryrefslogtreecommitdiff
path: root/mojo/public/cpp/bindings/struct_ptr.h
diff options
context:
space:
mode:
authorHidehiko Abe <hidehiko@google.com>2017-12-13 19:00:02 +0900
committerHidehiko Abe <hidehiko@google.com>2017-12-13 23:42:13 +0900
commit0411add1e14cc2dc041f5f1776f05a8c4b787d73 (patch)
tree19a081baf4afcba8d442b5e839cb1ff247f31b7f /mojo/public/cpp/bindings/struct_ptr.h
parentc96e5aa6f5f1f6df03ef539b4b85c78bf7c292e5 (diff)
downloadlibmojo-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.h203
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_