You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
293 lines
7.3 KiB
293 lines
7.3 KiB
// Copyright 2014 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#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 StructPtrWTFHelper;
|
|
|
|
template <typename Struct>
|
|
class InlinedStructPtrWTFHelper;
|
|
|
|
} // namespace internal
|
|
|
|
// Smart pointer wrapping a mojom structure with move-only semantics.
|
|
template <typename S>
|
|
class StructPtr {
|
|
public:
|
|
using Struct = S;
|
|
|
|
StructPtr() = default;
|
|
StructPtr(decltype(nullptr)) {}
|
|
|
|
~StructPtr() = default;
|
|
|
|
StructPtr& operator=(decltype(nullptr)) {
|
|
reset();
|
|
return *this;
|
|
}
|
|
|
|
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() { ptr_.reset(); }
|
|
|
|
bool is_null() const { return !ptr_; }
|
|
|
|
Struct& operator*() const {
|
|
DCHECK(ptr_);
|
|
return *ptr_;
|
|
}
|
|
Struct* operator->() const {
|
|
DCHECK(ptr_);
|
|
return ptr_.get();
|
|
}
|
|
Struct* get() const { return ptr_.get(); }
|
|
|
|
void Swap(StructPtr* other) { std::swap(ptr_, other->ptr_); }
|
|
|
|
// Please note that calling this method will fail compilation if the value
|
|
// type |Struct| doesn't have a Clone() method defined (which usually means
|
|
// that it contains Mojo handles).
|
|
StructPtr Clone() const { return is_null() ? StructPtr() : ptr_->Clone(); }
|
|
|
|
// Compares the pointees (which might both be null).
|
|
// TODO(crbug.com/735302): 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_);
|
|
}
|
|
|
|
// 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);
|
|
}
|
|
|
|
explicit operator bool() const { return !is_null(); }
|
|
|
|
bool operator<(const StructPtr& other) const {
|
|
return Hash(internal::kHashSeed) < other.Hash(internal::kHashSeed);
|
|
}
|
|
|
|
private:
|
|
friend class internal::StructPtrWTFHelper<Struct>;
|
|
void Take(StructPtr* other) {
|
|
reset();
|
|
Swap(other);
|
|
}
|
|
|
|
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() : state_(NIL) {}
|
|
InlinedStructPtr(decltype(nullptr)) : state_(NIL) {}
|
|
|
|
~InlinedStructPtr() {}
|
|
|
|
InlinedStructPtr& operator=(decltype(nullptr)) {
|
|
reset();
|
|
return *this;
|
|
}
|
|
|
|
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() {
|
|
state_ = NIL;
|
|
value_. ~Struct();
|
|
new (&value_) Struct();
|
|
}
|
|
|
|
bool is_null() const { return state_ == NIL; }
|
|
|
|
Struct& operator*() const {
|
|
DCHECK(state_ == VALID);
|
|
return value_;
|
|
}
|
|
Struct* operator->() const {
|
|
DCHECK(state_ == VALID);
|
|
return &value_;
|
|
}
|
|
Struct* get() const { return &value_; }
|
|
|
|
void Swap(InlinedStructPtr* other) {
|
|
std::swap(value_, other->value_);
|
|
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_);
|
|
}
|
|
|
|
// 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);
|
|
}
|
|
|
|
explicit operator bool() const { return !is_null(); }
|
|
|
|
bool operator<(const InlinedStructPtr& other) const {
|
|
return Hash(internal::kHashSeed) < other.Hash(internal::kHashSeed);
|
|
}
|
|
|
|
private:
|
|
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_;
|
|
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_
|