| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 // unique_ptr-style pointer that stores values that may be from an arena. Takes | |
| 6 // up the same storage as the platform's native pointer type. Takes ownership | |
| 7 // of the value it's constructed with; if holding a value in an arena, and the | |
| 8 // type has a non-trivial destructor, the arena must outlive the | |
| 9 // QuicArenaScopedPtr. Does not support array overloads. | |
| 10 | |
| 11 #ifndef NET_QUIC_QUIC_ARENA_SCOPED_PTR_H_ | |
| 12 #define NET_QUIC_QUIC_ARENA_SCOPED_PTR_H_ | |
| 13 | |
| 14 #include <cstdint> // for uintptr_t | |
| 15 | |
| 16 #include "base/logging.h" | |
| 17 #include "base/macros.h" | |
| 18 #include "net/quic/quic_utils.h" | |
| 19 | |
| 20 namespace net { | |
| 21 | |
| 22 template <typename T> | |
| 23 class QuicArenaScopedPtr { | |
| 24 static_assert(QUIC_ALIGN_OF(T*) > 1, | |
| 25 "QuicArenaScopedPtr can only store objects that are aligned to " | |
| 26 "greater than 1 byte."); | |
| 27 | |
| 28 public: | |
| 29 // Constructs an empty QuicArenaScopedPtr. | |
| 30 QuicArenaScopedPtr(); | |
| 31 | |
| 32 // Constructs a QuicArenaScopedPtr referencing the heap-allocated memory | |
| 33 // provided. | |
| 34 explicit QuicArenaScopedPtr(T* value); | |
| 35 | |
| 36 template <typename U> | |
| 37 QuicArenaScopedPtr(QuicArenaScopedPtr<U>&& other); // NOLINT | |
| 38 template <typename U> | |
| 39 QuicArenaScopedPtr& operator=(QuicArenaScopedPtr<U>&& other); | |
| 40 ~QuicArenaScopedPtr(); | |
| 41 | |
| 42 // Returns a pointer to the value. | |
| 43 T* get() const; | |
| 44 | |
| 45 // Returns a reference to the value. | |
| 46 T& operator*() const; | |
| 47 | |
| 48 // Returns a pointer to the value. | |
| 49 T* operator->() const; | |
| 50 | |
| 51 // Swaps the value of this pointer with |other|. | |
| 52 void swap(QuicArenaScopedPtr& other); | |
| 53 | |
| 54 // Resets the held value to |value|. | |
| 55 void reset(T* value = nullptr); | |
| 56 | |
| 57 // Returns true if |this| came from an arena. Primarily exposed for testing | |
| 58 // and assertions. | |
| 59 bool is_from_arena(); | |
| 60 | |
| 61 private: | |
| 62 // Friends with other derived types of QuicArenaScopedPtr, to support the | |
| 63 // derived-types case. | |
| 64 template <typename U> | |
| 65 friend class QuicArenaScopedPtr; | |
| 66 // Also befriend all known arenas, only to prevent misuse. | |
| 67 template <uint32_t ArenaSize> | |
| 68 friend class QuicOneBlockArena; | |
| 69 | |
| 70 // Tag to denote that a QuicArenaScopedPtr is being explicitly created by an | |
| 71 // arena. | |
| 72 enum class ConstructFrom { kHeap, kArena }; | |
| 73 | |
| 74 // Constructs a QuicArenaScopedPtr with the given representation. | |
| 75 QuicArenaScopedPtr(void* value, ConstructFrom from); | |
| 76 | |
| 77 // Low-order bits of value_ that determine if the pointer came from an arena. | |
| 78 static const uintptr_t kFromArenaMask = 0x1; | |
| 79 | |
| 80 // Every platform we care about has at least 4B aligned integers, so store the | |
| 81 // is_from_arena bit in the least significant bit. | |
| 82 void* value_; | |
| 83 | |
| 84 DISALLOW_COPY_AND_ASSIGN(QuicArenaScopedPtr); | |
| 85 }; | |
| 86 | |
| 87 template <typename T> | |
| 88 bool operator==(const QuicArenaScopedPtr<T>& left, | |
| 89 const QuicArenaScopedPtr<T>& right) { | |
| 90 return left.get() == right.get(); | |
| 91 } | |
| 92 | |
| 93 template <typename T> | |
| 94 bool operator!=(const QuicArenaScopedPtr<T>& left, | |
| 95 const QuicArenaScopedPtr<T>& right) { | |
| 96 return left.get() != right.get(); | |
| 97 } | |
| 98 | |
| 99 template <typename T> | |
| 100 bool operator==(std::nullptr_t, const QuicArenaScopedPtr<T>& right) { | |
| 101 return nullptr == right.get(); | |
| 102 } | |
| 103 | |
| 104 template <typename T> | |
| 105 bool operator!=(std::nullptr_t, const QuicArenaScopedPtr<T>& right) { | |
| 106 return nullptr != right.get(); | |
| 107 } | |
| 108 | |
| 109 template <typename T> | |
| 110 bool operator==(const QuicArenaScopedPtr<T>& left, std::nullptr_t) { | |
| 111 return left.get() == nullptr; | |
| 112 } | |
| 113 | |
| 114 template <typename T> | |
| 115 bool operator!=(const QuicArenaScopedPtr<T>& left, std::nullptr_t) { | |
| 116 return left.get() != nullptr; | |
| 117 } | |
| 118 | |
| 119 template <typename T> | |
| 120 QuicArenaScopedPtr<T>::QuicArenaScopedPtr() | |
| 121 : value_(nullptr) {} | |
| 122 | |
| 123 template <typename T> | |
| 124 QuicArenaScopedPtr<T>::QuicArenaScopedPtr(T* value) | |
| 125 : QuicArenaScopedPtr(value, ConstructFrom::kHeap) {} | |
| 126 | |
| 127 template <typename T> | |
| 128 template <typename U> | |
| 129 QuicArenaScopedPtr<T>::QuicArenaScopedPtr(QuicArenaScopedPtr<U>&& other) | |
| 130 : value_(other.value_) { | |
| 131 static_assert( | |
| 132 std::is_base_of<T, U>::value || std::is_same<T, U>::value, | |
| 133 "Cannot construct QuicArenaScopedPtr; type is not derived or same."); | |
| 134 other.value_ = nullptr; | |
| 135 } | |
| 136 | |
| 137 template <typename T> | |
| 138 template <typename U> | |
| 139 QuicArenaScopedPtr<T>& QuicArenaScopedPtr<T>::operator=( | |
| 140 QuicArenaScopedPtr<U>&& other) { | |
| 141 static_assert( | |
| 142 std::is_base_of<T, U>::value || std::is_same<T, U>::value, | |
| 143 "Cannot assign QuicArenaScopedPtr; type is not derived or same."); | |
| 144 swap(other); | |
| 145 return *this; | |
| 146 } | |
| 147 | |
| 148 template <typename T> | |
| 149 QuicArenaScopedPtr<T>::~QuicArenaScopedPtr() { | |
| 150 reset(); | |
| 151 } | |
| 152 | |
| 153 template <typename T> | |
| 154 T* QuicArenaScopedPtr<T>::get() const { | |
| 155 return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(value_) & | |
| 156 ~kFromArenaMask); | |
| 157 } | |
| 158 | |
| 159 template <typename T> | |
| 160 T& QuicArenaScopedPtr<T>::operator*() const { | |
| 161 return *get(); | |
| 162 } | |
| 163 | |
| 164 template <typename T> | |
| 165 T* QuicArenaScopedPtr<T>::operator->() const { | |
| 166 return get(); | |
| 167 } | |
| 168 | |
| 169 template <typename T> | |
| 170 void QuicArenaScopedPtr<T>::swap(QuicArenaScopedPtr& other) { | |
| 171 using std::swap; | |
| 172 swap(value_, other.value_); | |
| 173 } | |
| 174 | |
| 175 template <typename T> | |
| 176 bool QuicArenaScopedPtr<T>::is_from_arena() { | |
| 177 return (reinterpret_cast<uintptr_t>(value_) & kFromArenaMask) != 0; | |
| 178 } | |
| 179 | |
| 180 template <typename T> | |
| 181 void QuicArenaScopedPtr<T>::reset(T* value) { | |
| 182 if (value_ != nullptr) { | |
| 183 if (is_from_arena()) { | |
| 184 // Manually invoke the destructor. | |
| 185 get()->~T(); | |
| 186 } else { | |
| 187 delete get(); | |
| 188 } | |
| 189 } | |
| 190 DCHECK_EQ(0u, reinterpret_cast<uintptr_t>(value) & kFromArenaMask); | |
| 191 value_ = value; | |
| 192 } | |
| 193 | |
| 194 template <typename T> | |
| 195 QuicArenaScopedPtr<T>::QuicArenaScopedPtr(void* value, ConstructFrom from_arena) | |
| 196 : value_(value) { | |
| 197 DCHECK_EQ(0u, reinterpret_cast<uintptr_t>(value_) & kFromArenaMask); | |
| 198 switch (from_arena) { | |
| 199 case ConstructFrom::kHeap: | |
| 200 break; | |
| 201 case ConstructFrom::kArena: | |
| 202 value_ = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(value_) | | |
| 203 QuicArenaScopedPtr<T>::kFromArenaMask); | |
| 204 break; | |
| 205 } | |
| 206 } | |
| 207 | |
| 208 } // namespace net | |
| 209 | |
| 210 #endif // NET_QUIC_QUIC_ARENA_SCOPED_PTR_H_ | |
| OLD | NEW |