| Index: net/quic/quic_arena_scoped_ptr.h
|
| diff --git a/net/quic/quic_arena_scoped_ptr.h b/net/quic/quic_arena_scoped_ptr.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..5083036f9075a726ed0bf1394f988f5dcddf44fe
|
| --- /dev/null
|
| +++ b/net/quic/quic_arena_scoped_ptr.h
|
| @@ -0,0 +1,210 @@
|
| +// Copyright (c) 2016 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.
|
| +
|
| +// unique_ptr-style pointer that stores values that may be from an arena. Takes
|
| +// up the same storage as the platform's native pointer type. Takes ownership
|
| +// of the value it's constructed with; if holding a value in an arena, and the
|
| +// type has a non-trivial destructor, the arena must outlive the
|
| +// QuicArenaScopedPtr. Does not support array overloads.
|
| +
|
| +#ifndef NET_QUIC_QUIC_ARENA_SCOPED_PTR_H_
|
| +#define NET_QUIC_QUIC_ARENA_SCOPED_PTR_H_
|
| +
|
| +#include <cstdint> // for uintptr_t
|
| +
|
| +#include "base/logging.h"
|
| +#include "base/macros.h"
|
| +#include "net/quic/quic_utils.h"
|
| +
|
| +namespace net {
|
| +
|
| +template <typename T>
|
| +class QuicArenaScopedPtr {
|
| + static_assert(QUIC_ALIGN_OF(T*) > 1,
|
| + "QuicArenaScopedPtr can only store objects that are aligned to "
|
| + "greater than 1 byte.");
|
| +
|
| + public:
|
| + // Constructs an empty QuicArenaScopedPtr.
|
| + QuicArenaScopedPtr();
|
| +
|
| + // Constructs a QuicArenaScopedPtr referencing the heap-allocated memory
|
| + // provided.
|
| + explicit QuicArenaScopedPtr(T* value);
|
| +
|
| + template <typename U>
|
| + QuicArenaScopedPtr(QuicArenaScopedPtr<U>&& other); // NOLINT
|
| + template <typename U>
|
| + QuicArenaScopedPtr& operator=(QuicArenaScopedPtr<U>&& other);
|
| + ~QuicArenaScopedPtr();
|
| +
|
| + // Returns a pointer to the value.
|
| + T* get() const;
|
| +
|
| + // Returns a reference to the value.
|
| + T& operator*() const;
|
| +
|
| + // Returns a pointer to the value.
|
| + T* operator->() const;
|
| +
|
| + // Swaps the value of this pointer with |other|.
|
| + void swap(QuicArenaScopedPtr& other);
|
| +
|
| + // Resets the held value to |value|.
|
| + void reset(T* value = nullptr);
|
| +
|
| + // Returns true if |this| came from an arena. Primarily exposed for testing
|
| + // and assertions.
|
| + bool is_from_arena();
|
| +
|
| + private:
|
| + // Friends with other derived types of QuicArenaScopedPtr, to support the
|
| + // derived-types case.
|
| + template <typename U>
|
| + friend class QuicArenaScopedPtr;
|
| + // Also befriend all known arenas, only to prevent misuse.
|
| + template <uint32_t ArenaSize>
|
| + friend class QuicOneBlockArena;
|
| +
|
| + // Tag to denote that a QuicArenaScopedPtr is being explicitly created by an
|
| + // arena.
|
| + enum class ConstructFrom { kHeap, kArena };
|
| +
|
| + // Constructs a QuicArenaScopedPtr with the given representation.
|
| + QuicArenaScopedPtr(void* value, ConstructFrom from);
|
| +
|
| + // Low-order bits of value_ that determine if the pointer came from an arena.
|
| + static const uintptr_t kFromArenaMask = 0x1;
|
| +
|
| + // Every platform we care about has at least 4B aligned integers, so store the
|
| + // is_from_arena bit in the least significant bit.
|
| + void* value_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(QuicArenaScopedPtr);
|
| +};
|
| +
|
| +template <typename T>
|
| +bool operator==(const QuicArenaScopedPtr<T>& left,
|
| + const QuicArenaScopedPtr<T>& right) {
|
| + return left.get() == right.get();
|
| +}
|
| +
|
| +template <typename T>
|
| +bool operator!=(const QuicArenaScopedPtr<T>& left,
|
| + const QuicArenaScopedPtr<T>& right) {
|
| + return left.get() != right.get();
|
| +}
|
| +
|
| +template <typename T>
|
| +bool operator==(std::nullptr_t, const QuicArenaScopedPtr<T>& right) {
|
| + return nullptr == right.get();
|
| +}
|
| +
|
| +template <typename T>
|
| +bool operator!=(std::nullptr_t, const QuicArenaScopedPtr<T>& right) {
|
| + return nullptr != right.get();
|
| +}
|
| +
|
| +template <typename T>
|
| +bool operator==(const QuicArenaScopedPtr<T>& left, std::nullptr_t) {
|
| + return left.get() == nullptr;
|
| +}
|
| +
|
| +template <typename T>
|
| +bool operator!=(const QuicArenaScopedPtr<T>& left, std::nullptr_t) {
|
| + return left.get() != nullptr;
|
| +}
|
| +
|
| +template <typename T>
|
| +QuicArenaScopedPtr<T>::QuicArenaScopedPtr()
|
| + : value_(nullptr) {}
|
| +
|
| +template <typename T>
|
| +QuicArenaScopedPtr<T>::QuicArenaScopedPtr(T* value)
|
| + : QuicArenaScopedPtr(value, ConstructFrom::kHeap) {}
|
| +
|
| +template <typename T>
|
| +template <typename U>
|
| +QuicArenaScopedPtr<T>::QuicArenaScopedPtr(QuicArenaScopedPtr<U>&& other)
|
| + : value_(other.value_) {
|
| + static_assert(
|
| + std::is_base_of<T, U>::value || std::is_same<T, U>::value,
|
| + "Cannot construct QuicArenaScopedPtr; type is not derived or same.");
|
| + other.value_ = nullptr;
|
| +}
|
| +
|
| +template <typename T>
|
| +template <typename U>
|
| +QuicArenaScopedPtr<T>& QuicArenaScopedPtr<T>::operator=(
|
| + QuicArenaScopedPtr<U>&& other) {
|
| + static_assert(
|
| + std::is_base_of<T, U>::value || std::is_same<T, U>::value,
|
| + "Cannot assign QuicArenaScopedPtr; type is not derived or same.");
|
| + swap(other);
|
| + return *this;
|
| +}
|
| +
|
| +template <typename T>
|
| +QuicArenaScopedPtr<T>::~QuicArenaScopedPtr() {
|
| + reset();
|
| +}
|
| +
|
| +template <typename T>
|
| +T* QuicArenaScopedPtr<T>::get() const {
|
| + return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(value_) &
|
| + ~kFromArenaMask);
|
| +}
|
| +
|
| +template <typename T>
|
| +T& QuicArenaScopedPtr<T>::operator*() const {
|
| + return *get();
|
| +}
|
| +
|
| +template <typename T>
|
| +T* QuicArenaScopedPtr<T>::operator->() const {
|
| + return get();
|
| +}
|
| +
|
| +template <typename T>
|
| +void QuicArenaScopedPtr<T>::swap(QuicArenaScopedPtr& other) {
|
| + using std::swap;
|
| + swap(value_, other.value_);
|
| +}
|
| +
|
| +template <typename T>
|
| +bool QuicArenaScopedPtr<T>::is_from_arena() {
|
| + return (reinterpret_cast<uintptr_t>(value_) & kFromArenaMask) != 0;
|
| +}
|
| +
|
| +template <typename T>
|
| +void QuicArenaScopedPtr<T>::reset(T* value) {
|
| + if (value_ != nullptr) {
|
| + if (is_from_arena()) {
|
| + // Manually invoke the destructor.
|
| + get()->~T();
|
| + } else {
|
| + delete get();
|
| + }
|
| + }
|
| + DCHECK_EQ(0u, reinterpret_cast<uintptr_t>(value) & kFromArenaMask);
|
| + value_ = value;
|
| +}
|
| +
|
| +template <typename T>
|
| +QuicArenaScopedPtr<T>::QuicArenaScopedPtr(void* value, ConstructFrom from_arena)
|
| + : value_(value) {
|
| + DCHECK_EQ(0u, reinterpret_cast<uintptr_t>(value_) & kFromArenaMask);
|
| + switch (from_arena) {
|
| + case ConstructFrom::kHeap:
|
| + break;
|
| + case ConstructFrom::kArena:
|
| + value_ = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(value_) |
|
| + QuicArenaScopedPtr<T>::kFromArenaMask);
|
| + break;
|
| + }
|
| +}
|
| +
|
| +} // namespace net
|
| +
|
| +#endif // NET_QUIC_QUIC_ARENA_SCOPED_PTR_H_
|
|
|