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 |