Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(94)

Side by Side Diff: base/memory/weak_ptr.h

Issue 2961083002: Move base::WeakPtr's null ctor out-of-line (Closed)
Patch Set: rebase Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | base/memory/weak_ptr.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Weak pointers are pointers to an object that do not affect its lifetime, 5 // Weak pointers are pointers to an object that do not affect its lifetime,
6 // and which may be invalidated (i.e. reset to nullptr) by the object, or its 6 // and which may be invalidated (i.e. reset to nullptr) by the object, or its
7 // owner, at any time, most commonly when the object is about to be deleted. 7 // owner, at any time, most commonly when the object is about to be deleted.
8 8
9 // Weak pointers are useful when an object needs to be accessed safely by one 9 // Weak pointers are useful when an object needs to be accessed safely by one
10 // or more objects other than its owner, and those callers can cope with the 10 // or more objects other than its owner, and those callers can cope with the
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 public: 193 public:
194 WeakPtrBase(); 194 WeakPtrBase();
195 ~WeakPtrBase(); 195 ~WeakPtrBase();
196 196
197 WeakPtrBase(const WeakPtrBase& other) = default; 197 WeakPtrBase(const WeakPtrBase& other) = default;
198 WeakPtrBase(WeakPtrBase&& other) = default; 198 WeakPtrBase(WeakPtrBase&& other) = default;
199 WeakPtrBase& operator=(const WeakPtrBase& other) = default; 199 WeakPtrBase& operator=(const WeakPtrBase& other) = default;
200 WeakPtrBase& operator=(WeakPtrBase&& other) = default; 200 WeakPtrBase& operator=(WeakPtrBase&& other) = default;
201 201
202 protected: 202 protected:
203 explicit WeakPtrBase(const WeakReference& ref); 203 WeakPtrBase(const WeakReference& ref, uintptr_t ptr);
204 204
205 WeakReference ref_; 205 WeakReference ref_;
206
207 // This pointer is only valid when ref_.is_valid() is true. Otherwise, its
208 // value is undefined (as opposed to nullptr).
209 uintptr_t ptr_;
206 }; 210 };
207 211
208 // This class provides a common implementation of common functions that would 212 // This class provides a common implementation of common functions that would
209 // otherwise get instantiated separately for each distinct instantiation of 213 // otherwise get instantiated separately for each distinct instantiation of
210 // SupportsWeakPtr<>. 214 // SupportsWeakPtr<>.
211 class SupportsWeakPtrBase { 215 class SupportsWeakPtrBase {
212 public: 216 public:
213 // A safe static downcast of a WeakPtr<Base> to WeakPtr<Derived>. This 217 // A safe static downcast of a WeakPtr<Base> to WeakPtr<Derived>. This
214 // conversion will only compile if there is exists a Base which inherits 218 // conversion will only compile if there is exists a Base which inherits
215 // from SupportsWeakPtr<Base>. See base::AsWeakPtr() below for a helper 219 // from SupportsWeakPtr<Base>. See base::AsWeakPtr() below for a helper
216 // function that makes calling this easier. 220 // function that makes calling this easier.
217 template<typename Derived> 221 template<typename Derived>
218 static WeakPtr<Derived> StaticAsWeakPtr(Derived* t) { 222 static WeakPtr<Derived> StaticAsWeakPtr(Derived* t) {
219 static_assert( 223 static_assert(
220 std::is_base_of<internal::SupportsWeakPtrBase, Derived>::value, 224 std::is_base_of<internal::SupportsWeakPtrBase, Derived>::value,
221 "AsWeakPtr argument must inherit from SupportsWeakPtr"); 225 "AsWeakPtr argument must inherit from SupportsWeakPtr");
222 return AsWeakPtrImpl<Derived>(t, *t); 226 return AsWeakPtrImpl<Derived>(t, *t);
223 } 227 }
224 228
225 private: 229 private:
226 // This template function uses type inference to find a Base of Derived 230 // This template function uses type inference to find a Base of Derived
227 // which is an instance of SupportsWeakPtr<Base>. We can then safely 231 // which is an instance of SupportsWeakPtr<Base>. We can then safely
228 // static_cast the Base* to a Derived*. 232 // static_cast the Base* to a Derived*.
229 template <typename Derived, typename Base> 233 template <typename Derived, typename Base>
230 static WeakPtr<Derived> AsWeakPtrImpl( 234 static WeakPtr<Derived> AsWeakPtrImpl(
231 Derived* t, const SupportsWeakPtr<Base>&) { 235 Derived* t, const SupportsWeakPtr<Base>&) {
232 WeakPtr<Base> ptr = t->Base::AsWeakPtr(); 236 WeakPtr<Base> ptr = t->Base::AsWeakPtr();
233 return WeakPtr<Derived>(ptr.ref_, static_cast<Derived*>(ptr.ptr_)); 237 return WeakPtr<Derived>(
238 ptr.ref_, static_cast<Derived*>(reinterpret_cast<Base*>(ptr.ptr_)));
234 } 239 }
235 }; 240 };
236 241
237 } // namespace internal 242 } // namespace internal
238 243
239 template <typename T> class WeakPtrFactory; 244 template <typename T> class WeakPtrFactory;
240 245
241 // The WeakPtr class holds a weak reference to |T*|. 246 // The WeakPtr class holds a weak reference to |T*|.
242 // 247 //
243 // This class is designed to be used like a normal pointer. You should always 248 // This class is designed to be used like a normal pointer. You should always
244 // null-test an object of this class before using it or invoking a method that 249 // null-test an object of this class before using it or invoking a method that
245 // may result in the underlying object being destroyed. 250 // may result in the underlying object being destroyed.
246 // 251 //
247 // EXAMPLE: 252 // EXAMPLE:
248 // 253 //
249 // class Foo { ... }; 254 // class Foo { ... };
250 // WeakPtr<Foo> foo; 255 // WeakPtr<Foo> foo;
251 // if (foo) 256 // if (foo)
252 // foo->method(); 257 // foo->method();
253 // 258 //
254 template <typename T> 259 template <typename T>
255 class WeakPtr : public internal::WeakPtrBase { 260 class WeakPtr : public internal::WeakPtrBase {
256 public: 261 public:
257 WeakPtr() : ptr_(nullptr) {} 262 WeakPtr() {}
258 263
259 WeakPtr(std::nullptr_t) : ptr_(nullptr) {} 264 WeakPtr(std::nullptr_t) {}
260 265
261 // Allow conversion from U to T provided U "is a" T. Note that this 266 // Allow conversion from U to T provided U "is a" T. Note that this
262 // is separate from the (implicit) copy and move constructors. 267 // is separate from the (implicit) copy and move constructors.
263 template <typename U> 268 template <typename U>
264 WeakPtr(const WeakPtr<U>& other) : WeakPtrBase(other), ptr_(other.ptr_) { 269 WeakPtr(const WeakPtr<U>& other) : WeakPtrBase(other) {
270 // Need to cast from U* to T* to do pointer adjustment in case of multiple
271 // inheritance. This also enforces the "U is a T" rule.
272 T* t = reinterpret_cast<U*>(other.ptr_);
273 ptr_ = reinterpret_cast<uintptr_t>(t);
265 } 274 }
266 template <typename U> 275 template <typename U>
267 WeakPtr(WeakPtr<U>&& other) 276 WeakPtr(WeakPtr<U>&& other) : WeakPtrBase(std::move(other)) {
268 : WeakPtrBase(std::move(other)), ptr_(other.ptr_) {} 277 // Need to cast from U* to T* to do pointer adjustment in case of multiple
278 // inheritance. This also enforces the "U is a T" rule.
279 T* t = reinterpret_cast<U*>(other.ptr_);
280 ptr_ = reinterpret_cast<uintptr_t>(t);
281 }
269 282
270 T* get() const { 283 T* get() const {
271 // Intentionally bitwise and; see command on Flag::IsValid(). This provides 284 // Intentionally bitwise and; see command on Flag::IsValid(). This provides
272 // a fast way of conditionally retrieving the pointer, and conveniently sets 285 // a fast way of conditionally retrieving the pointer, and conveniently sets
273 // EFLAGS for any null-check performed by the caller. 286 // EFLAGS for any null-check performed by the caller.
274 return reinterpret_cast<T*>(ref_.is_valid() & 287 return reinterpret_cast<T*>(ref_.is_valid() & ptr_);
275 reinterpret_cast<uintptr_t>(ptr_));
276 } 288 }
277 289
278 T& operator*() const { 290 T& operator*() const {
279 DCHECK(get() != nullptr); 291 DCHECK(get() != nullptr);
280 return *get(); 292 return *get();
281 } 293 }
282 T* operator->() const { 294 T* operator->() const {
283 DCHECK(get() != nullptr); 295 DCHECK(get() != nullptr);
284 return get(); 296 return get();
285 } 297 }
286 298
287 void reset() { 299 void reset() {
288 ref_ = internal::WeakReference(); 300 ref_ = internal::WeakReference();
289 ptr_ = nullptr; 301 ptr_ = 0;
290 } 302 }
291 303
292 // Allow conditionals to test validity, e.g. if (weak_ptr) {...}; 304 // Allow conditionals to test validity, e.g. if (weak_ptr) {...};
293 explicit operator bool() const { return get() != nullptr; } 305 explicit operator bool() const { return get() != nullptr; }
294 306
295 private: 307 private:
296 friend class internal::SupportsWeakPtrBase; 308 friend class internal::SupportsWeakPtrBase;
297 template <typename U> friend class WeakPtr; 309 template <typename U> friend class WeakPtr;
298 friend class SupportsWeakPtr<T>; 310 friend class SupportsWeakPtr<T>;
299 friend class WeakPtrFactory<T>; 311 friend class WeakPtrFactory<T>;
300 312
301 WeakPtr(const internal::WeakReference& ref, T* ptr) 313 WeakPtr(const internal::WeakReference& ref, T* ptr)
302 : WeakPtrBase(ref), 314 : WeakPtrBase(ref, reinterpret_cast<uintptr_t>(ptr)) {}
303 ptr_(ptr) {
304 }
305
306 // This pointer is only valid when ref_.is_valid() is true. Otherwise, its
307 // value is undefined (as opposed to nullptr).
308 T* ptr_;
309 }; 315 };
310 316
311 // Allow callers to compare WeakPtrs against nullptr to test validity. 317 // Allow callers to compare WeakPtrs against nullptr to test validity.
312 template <class T> 318 template <class T>
313 bool operator!=(const WeakPtr<T>& weak_ptr, std::nullptr_t) { 319 bool operator!=(const WeakPtr<T>& weak_ptr, std::nullptr_t) {
314 return !(weak_ptr == nullptr); 320 return !(weak_ptr == nullptr);
315 } 321 }
316 template <class T> 322 template <class T>
317 bool operator!=(std::nullptr_t, const WeakPtr<T>& weak_ptr) { 323 bool operator!=(std::nullptr_t, const WeakPtr<T>& weak_ptr) {
318 return weak_ptr != nullptr; 324 return weak_ptr != nullptr;
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 // base::WeakPtr<Derived> ptr = derived.AsWeakPtr(); // Fails. 418 // base::WeakPtr<Derived> ptr = derived.AsWeakPtr(); // Fails.
413 419
414 template <typename Derived> 420 template <typename Derived>
415 WeakPtr<Derived> AsWeakPtr(Derived* t) { 421 WeakPtr<Derived> AsWeakPtr(Derived* t) {
416 return internal::SupportsWeakPtrBase::StaticAsWeakPtr<Derived>(t); 422 return internal::SupportsWeakPtrBase::StaticAsWeakPtr<Derived>(t);
417 } 423 }
418 424
419 } // namespace base 425 } // namespace base
420 426
421 #endif // BASE_MEMORY_WEAK_PTR_H_ 427 #endif // BASE_MEMORY_WEAK_PTR_H_
OLDNEW
« no previous file with comments | « no previous file | base/memory/weak_ptr.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698