Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 88 // These classes are part of the WeakPtr implementation. | 88 // These classes are part of the WeakPtr implementation. |
| 89 // DO NOT USE THESE CLASSES DIRECTLY YOURSELF. | 89 // DO NOT USE THESE CLASSES DIRECTLY YOURSELF. |
| 90 | 90 |
| 91 class BASE_EXPORT WeakReference { | 91 class BASE_EXPORT WeakReference { |
| 92 public: | 92 public: |
| 93 // Although Flag is bound to a specific SequencedTaskRunner, it may be | 93 // Although Flag is bound to a specific SequencedTaskRunner, it may be |
| 94 // deleted from another via base::WeakPtr::~WeakPtr(). | 94 // deleted from another via base::WeakPtr::~WeakPtr(). |
| 95 class BASE_EXPORT Flag : public RefCountedThreadSafe<Flag> { | 95 class BASE_EXPORT Flag : public RefCountedThreadSafe<Flag> { |
| 96 public: | 96 public: |
| 97 Flag(); | 97 Flag(); |
| 98 static Flag* nullFlag(); | |
|
Nico
2017/06/28 14:54:10
google (and chromium) style spells functions NullF
hans
2017/06/28 20:37:35
Done.
| |
| 98 | 99 |
| 99 void Invalidate(); | 100 void Invalidate() { |
| 100 bool IsValid() const; | 101 #if DCHECK_IS_ON() |
| 102 if (this == nullFlag()) | |
| 103 return; | |
|
Nico
2017/06/28 14:54:09
This looks kind of confusing – do you not want to
hans
2017/06/28 20:37:35
I've tried to make this clearer with a comment. Th
| |
| 104 // The flag being invalidated with a single ref implies that there are no | |
| 105 // weak pointers in existence. Allow deletion on other thread in this | |
| 106 // case. | |
| 107 DCHECK(sequence_checker_.CalledOnValidSequence() || HasOneRef()) | |
| 108 << "WeakPtrs must be invalidated on the same sequenced thread."; | |
| 109 #endif | |
| 110 is_valid_ = 0; | |
| 111 } | |
| 112 uintptr_t IsValid() const { | |
|
Nico
2017/06/28 14:54:10
Add comment that this returns either all 0s or all
hans
2017/06/28 20:37:35
Done.
| |
| 113 #if DCHECK_IS_ON() | |
| 114 if (this == nullFlag()) { | |
| 115 DCHECK(!is_valid_); | |
| 116 return 0; | |
| 117 } | |
| 118 DCHECK(sequence_checker_.CalledOnValidSequence()) | |
| 119 << "WeakPtrs must be checked on the same sequenced thread."; | |
| 120 #endif | |
| 121 return is_valid_; | |
| 122 } | |
| 101 | 123 |
| 102 private: | 124 private: |
| 103 friend class base::RefCountedThreadSafe<Flag>; | 125 friend class base::RefCountedThreadSafe<Flag>; |
| 104 | 126 |
| 127 enum NullFlagTag { kNullFlagTag }; | |
| 128 Flag(NullFlagTag); | |
| 129 | |
| 105 ~Flag(); | 130 ~Flag(); |
| 106 | 131 |
| 132 uintptr_t is_valid_; | |
| 133 #if DCHECK_IS_ON() | |
| 134 // Even if SequenceChecker is an empty class in non-dcheck builds, it still | |
| 135 // takes up space in the class. | |
|
Nico
2017/06/28 14:36:56
This bit seems unrelated to what's in the CL descr
hans
2017/06/28 20:37:35
It's related in that it keeps the size from growin
Nico
2017/06/28 20:57:03
Ah ok, sounds good then
| |
| 107 SequenceChecker sequence_checker_; | 136 SequenceChecker sequence_checker_; |
| 108 bool is_valid_; | 137 #endif |
| 109 }; | 138 }; |
| 110 | 139 |
| 111 WeakReference(); | 140 WeakReference(); |
| 112 explicit WeakReference(const Flag* flag); | 141 explicit WeakReference(const Flag* flag); |
| 113 ~WeakReference(); | 142 ~WeakReference(); |
| 114 | 143 |
| 115 WeakReference(WeakReference&& other); | 144 WeakReference(WeakReference&& other); |
| 116 WeakReference(const WeakReference& other); | 145 WeakReference(const WeakReference& other); |
| 117 WeakReference& operator=(WeakReference&& other) = default; | 146 WeakReference& operator=(WeakReference&& other) = default; |
| 118 WeakReference& operator=(const WeakReference& other) = default; | 147 WeakReference& operator=(const WeakReference& other) = default; |
| 119 | 148 |
| 120 bool is_valid() const; | 149 uintptr_t is_valid() const { return flag_->IsValid(); } |
| 121 | 150 |
| 122 private: | 151 private: |
| 152 // Note: To avoid null-checks, flag_ always points to either Flag::nullFlag() | |
| 153 // or some other object. | |
| 123 scoped_refptr<const Flag> flag_; | 154 scoped_refptr<const Flag> flag_; |
| 124 }; | 155 }; |
| 125 | 156 |
| 126 class BASE_EXPORT WeakReferenceOwner { | 157 class BASE_EXPORT WeakReferenceOwner { |
| 127 public: | 158 public: |
| 128 WeakReferenceOwner(); | 159 WeakReferenceOwner(); |
| 129 ~WeakReferenceOwner(); | 160 ~WeakReferenceOwner(); |
| 130 | 161 |
| 131 WeakReference GetRef() const; | 162 WeakReference GetRef() const; |
| 132 | 163 |
| 133 bool HasRefs() const { | 164 bool HasRefs() const { return flag_->IsValid() && !flag_->HasOneRef(); } |
| 134 return flag_.get() && !flag_->HasOneRef(); | |
| 135 } | |
| 136 | 165 |
| 137 void Invalidate(); | 166 void Invalidate(); |
| 138 | 167 |
| 139 private: | 168 private: |
| 140 mutable scoped_refptr<WeakReference::Flag> flag_; | 169 mutable scoped_refptr<WeakReference::Flag> flag_; |
| 141 }; | 170 }; |
| 142 | 171 |
| 143 // This class simplifies the implementation of WeakPtr's type conversion | 172 // This class simplifies the implementation of WeakPtr's type conversion |
| 144 // constructor by avoiding the need for a public accessor for ref_. A | 173 // constructor by avoiding the need for a public accessor for ref_. A |
| 145 // WeakPtr<T> cannot access the private members of WeakPtr<U>, so this | 174 // WeakPtr<T> cannot access the private members of WeakPtr<U>, so this |
| 146 // base class gives us a way to access ref_ in a protected fashion. | 175 // base class gives us a way to access ref_ in a protected fashion. |
| 147 class BASE_EXPORT WeakPtrBase { | 176 class BASE_EXPORT WeakPtrBase { |
| 148 public: | 177 public: |
| 149 WeakPtrBase(); | 178 WeakPtrBase(); |
| 150 ~WeakPtrBase(); | 179 ~WeakPtrBase(); |
| 151 | 180 |
| 152 WeakPtrBase(const WeakPtrBase& other) = default; | 181 WeakPtrBase(const WeakPtrBase& other) = default; |
| 153 WeakPtrBase(WeakPtrBase&& other) = default; | 182 WeakPtrBase(WeakPtrBase&& other) = default; |
| 154 WeakPtrBase& operator=(const WeakPtrBase& other) = default; | 183 WeakPtrBase& operator=(const WeakPtrBase& other) = default; |
| 155 WeakPtrBase& operator=(WeakPtrBase&& other) = default; | 184 WeakPtrBase& operator=(WeakPtrBase&& other) = default; |
| 156 | 185 |
| 157 protected: | 186 protected: |
| 158 explicit WeakPtrBase(const WeakReference& ref); | 187 explicit WeakPtrBase(const WeakReference& ref); |
| 159 | 188 |
| 160 WeakReference ref_; | 189 WeakReference ref_; |
| 190 | |
| 191 // This pointer is only valid when ref_.is_valid() is true. Otherwise, its | |
| 192 // value is undefined (as opposed to nullptr). | |
| 193 uintptr_t ptr_; | |
|
Nico
2017/06/28 14:54:10
Moving this to the base class also feels kind of u
hans
2017/06/28 20:37:35
Done. Splitting this out.
| |
| 161 }; | 194 }; |
| 162 | 195 |
| 163 // This class provides a common implementation of common functions that would | 196 // This class provides a common implementation of common functions that would |
| 164 // otherwise get instantiated separately for each distinct instantiation of | 197 // otherwise get instantiated separately for each distinct instantiation of |
| 165 // SupportsWeakPtr<>. | 198 // SupportsWeakPtr<>. |
| 166 class SupportsWeakPtrBase { | 199 class SupportsWeakPtrBase { |
| 167 public: | 200 public: |
| 168 // A safe static downcast of a WeakPtr<Base> to WeakPtr<Derived>. This | 201 // A safe static downcast of a WeakPtr<Base> to WeakPtr<Derived>. This |
| 169 // conversion will only compile if there is exists a Base which inherits | 202 // conversion will only compile if there is exists a Base which inherits |
| 170 // from SupportsWeakPtr<Base>. See base::AsWeakPtr() below for a helper | 203 // from SupportsWeakPtr<Base>. See base::AsWeakPtr() below for a helper |
| 171 // function that makes calling this easier. | 204 // function that makes calling this easier. |
| 172 template<typename Derived> | 205 template<typename Derived> |
| 173 static WeakPtr<Derived> StaticAsWeakPtr(Derived* t) { | 206 static WeakPtr<Derived> StaticAsWeakPtr(Derived* t) { |
| 174 static_assert( | 207 static_assert( |
| 175 std::is_base_of<internal::SupportsWeakPtrBase, Derived>::value, | 208 std::is_base_of<internal::SupportsWeakPtrBase, Derived>::value, |
| 176 "AsWeakPtr argument must inherit from SupportsWeakPtr"); | 209 "AsWeakPtr argument must inherit from SupportsWeakPtr"); |
| 177 return AsWeakPtrImpl<Derived>(t, *t); | 210 return AsWeakPtrImpl<Derived>(t, *t); |
| 178 } | 211 } |
| 179 | 212 |
| 180 private: | 213 private: |
| 181 // This template function uses type inference to find a Base of Derived | 214 // This template function uses type inference to find a Base of Derived |
| 182 // which is an instance of SupportsWeakPtr<Base>. We can then safely | 215 // which is an instance of SupportsWeakPtr<Base>. We can then safely |
| 183 // static_cast the Base* to a Derived*. | 216 // static_cast the Base* to a Derived*. |
| 184 template <typename Derived, typename Base> | 217 template <typename Derived, typename Base> |
| 185 static WeakPtr<Derived> AsWeakPtrImpl( | 218 static WeakPtr<Derived> AsWeakPtrImpl( |
| 186 Derived* t, const SupportsWeakPtr<Base>&) { | 219 Derived* t, const SupportsWeakPtr<Base>&) { |
| 187 WeakPtr<Base> ptr = t->Base::AsWeakPtr(); | 220 WeakPtr<Base> ptr = t->Base::AsWeakPtr(); |
| 188 return WeakPtr<Derived>(ptr.ref_, static_cast<Derived*>(ptr.ptr_)); | 221 return WeakPtr<Derived>( |
| 222 ptr.ref_, static_cast<Derived*>(reinterpret_cast<Base*>(ptr.ptr_))); | |
| 189 } | 223 } |
| 190 }; | 224 }; |
| 191 | 225 |
| 192 } // namespace internal | 226 } // namespace internal |
| 193 | 227 |
| 194 template <typename T> class WeakPtrFactory; | 228 template <typename T> class WeakPtrFactory; |
| 195 | 229 |
| 196 // The WeakPtr class holds a weak reference to |T*|. | 230 // The WeakPtr class holds a weak reference to |T*|. |
| 197 // | 231 // |
| 198 // This class is designed to be used like a normal pointer. You should always | 232 // This class is designed to be used like a normal pointer. You should always |
| 199 // null-test an object of this class before using it or invoking a method that | 233 // null-test an object of this class before using it or invoking a method that |
| 200 // may result in the underlying object being destroyed. | 234 // may result in the underlying object being destroyed. |
| 201 // | 235 // |
| 202 // EXAMPLE: | 236 // EXAMPLE: |
| 203 // | 237 // |
| 204 // class Foo { ... }; | 238 // class Foo { ... }; |
| 205 // WeakPtr<Foo> foo; | 239 // WeakPtr<Foo> foo; |
| 206 // if (foo) | 240 // if (foo) |
| 207 // foo->method(); | 241 // foo->method(); |
| 208 // | 242 // |
| 209 template <typename T> | 243 template <typename T> |
| 210 class WeakPtr : public internal::WeakPtrBase { | 244 class WeakPtr : public internal::WeakPtrBase { |
| 211 public: | 245 public: |
| 212 WeakPtr() : ptr_(nullptr) {} | 246 WeakPtr() {} |
| 213 | 247 |
| 214 WeakPtr(std::nullptr_t) : ptr_(nullptr) {} | 248 WeakPtr(std::nullptr_t) {} |
| 215 | 249 |
| 216 // Allow conversion from U to T provided U "is a" T. Note that this | 250 // Allow conversion from U to T provided U "is a" T. Note that this |
| 217 // is separate from the (implicit) copy and move constructors. | 251 // is separate from the (implicit) copy and move constructors. |
| 218 template <typename U> | 252 template <typename U> |
| 219 WeakPtr(const WeakPtr<U>& other) : WeakPtrBase(other), ptr_(other.ptr_) { | 253 WeakPtr(const WeakPtr<U>& other) : WeakPtrBase(other) { |
| 254 static_assert(std::is_base_of<T, U>::value, | |
| 255 "other must be a subclass of T"); | |
| 220 } | 256 } |
| 221 template <typename U> | 257 template <typename U> |
| 222 WeakPtr(WeakPtr<U>&& other) | 258 WeakPtr(WeakPtr<U>&& other) : WeakPtrBase(std::move(other)) { |
| 223 : WeakPtrBase(std::move(other)), ptr_(other.ptr_) {} | 259 static_assert(std::is_base_of<T, U>::value, |
| 260 "other must be a subclass of T"); | |
| 261 } | |
| 224 | 262 |
| 225 T* get() const { return ref_.is_valid() ? ptr_ : nullptr; } | 263 T* get() const { return reinterpret_cast<T*>(ref_.is_valid() & ptr_); } |
|
Nico
2017/06/28 14:54:09
Since this is so unusual, I'd probably add `// Int
hans
2017/06/28 20:37:35
Done.
| |
| 226 | 264 |
| 227 T& operator*() const { | 265 T& operator*() const { |
| 228 DCHECK(get() != nullptr); | 266 DCHECK(get() != nullptr); |
| 229 return *get(); | 267 return *get(); |
| 230 } | 268 } |
| 231 T* operator->() const { | 269 T* operator->() const { |
| 232 DCHECK(get() != nullptr); | 270 DCHECK(get() != nullptr); |
| 233 return get(); | 271 return get(); |
| 234 } | 272 } |
| 235 | 273 |
| 236 void reset() { | 274 void reset() { |
| 237 ref_ = internal::WeakReference(); | 275 ref_ = internal::WeakReference(); |
| 238 ptr_ = nullptr; | 276 ptr_ = 0; |
| 239 } | 277 } |
| 240 | 278 |
| 241 // Allow conditionals to test validity, e.g. if (weak_ptr) {...}; | 279 // Allow conditionals to test validity, e.g. if (weak_ptr) {...}; |
| 242 explicit operator bool() const { return get() != nullptr; } | 280 explicit operator bool() const { return get() != nullptr; } |
| 243 | 281 |
| 244 private: | 282 private: |
| 245 friend class internal::SupportsWeakPtrBase; | 283 friend class internal::SupportsWeakPtrBase; |
| 246 template <typename U> friend class WeakPtr; | 284 template <typename U> friend class WeakPtr; |
| 247 friend class SupportsWeakPtr<T>; | 285 friend class SupportsWeakPtr<T>; |
| 248 friend class WeakPtrFactory<T>; | 286 friend class WeakPtrFactory<T>; |
| 249 | 287 |
| 250 WeakPtr(const internal::WeakReference& ref, T* ptr) | 288 WeakPtr(const internal::WeakReference& ref, T* ptr) : WeakPtrBase(ref) { |
| 251 : WeakPtrBase(ref), | 289 ptr_ = reinterpret_cast<uintptr_t>(ptr); |
| 252 ptr_(ptr) { | |
| 253 } | 290 } |
| 254 | |
| 255 // This pointer is only valid when ref_.is_valid() is true. Otherwise, its | |
| 256 // value is undefined (as opposed to nullptr). | |
| 257 T* ptr_; | |
| 258 }; | 291 }; |
| 259 | 292 |
| 260 // Allow callers to compare WeakPtrs against nullptr to test validity. | 293 // Allow callers to compare WeakPtrs against nullptr to test validity. |
| 261 template <class T> | 294 template <class T> |
| 262 bool operator!=(const WeakPtr<T>& weak_ptr, std::nullptr_t) { | 295 bool operator!=(const WeakPtr<T>& weak_ptr, std::nullptr_t) { |
| 263 return !(weak_ptr == nullptr); | 296 return !(weak_ptr == nullptr); |
| 264 } | 297 } |
| 265 template <class T> | 298 template <class T> |
| 266 bool operator!=(std::nullptr_t, const WeakPtr<T>& weak_ptr) { | 299 bool operator!=(std::nullptr_t, const WeakPtr<T>& weak_ptr) { |
| 267 return weak_ptr != nullptr; | 300 return weak_ptr != nullptr; |
| 268 } | 301 } |
| 269 template <class T> | 302 template <class T> |
| 270 bool operator==(const WeakPtr<T>& weak_ptr, std::nullptr_t) { | 303 bool operator==(const WeakPtr<T>& weak_ptr, std::nullptr_t) { |
| 271 return weak_ptr.get() == nullptr; | 304 return weak_ptr.get() == nullptr; |
| 272 } | 305 } |
| 273 template <class T> | 306 template <class T> |
| 274 bool operator==(std::nullptr_t, const WeakPtr<T>& weak_ptr) { | 307 bool operator==(std::nullptr_t, const WeakPtr<T>& weak_ptr) { |
| 275 return weak_ptr == nullptr; | 308 return weak_ptr == nullptr; |
| 276 } | 309 } |
| 277 | 310 |
| 311 namespace internal { | |
| 312 class BASE_EXPORT WeakPtrFactoryBase { | |
| 313 protected: | |
| 314 WeakPtrFactoryBase(uintptr_t ptr); | |
| 315 ~WeakPtrFactoryBase(); | |
| 316 internal::WeakReferenceOwner weak_reference_owner_; | |
| 317 uintptr_t ptr_; | |
| 318 }; | |
| 319 } // namespace internal | |
| 320 | |
| 278 // A class may be composed of a WeakPtrFactory and thereby | 321 // A class may be composed of a WeakPtrFactory and thereby |
| 279 // control how it exposes weak pointers to itself. This is helpful if you only | 322 // control how it exposes weak pointers to itself. This is helpful if you only |
| 280 // need weak pointers within the implementation of a class. This class is also | 323 // need weak pointers within the implementation of a class. This class is also |
| 281 // useful when working with primitive types. For example, you could have a | 324 // useful when working with primitive types. For example, you could have a |
| 282 // WeakPtrFactory<bool> that is used to pass around a weak reference to a bool. | 325 // WeakPtrFactory<bool> that is used to pass around a weak reference to a bool. |
| 283 template <class T> | 326 template <class T> |
| 284 class WeakPtrFactory { | 327 class WeakPtrFactory : public internal::WeakPtrFactoryBase { |
| 285 public: | 328 public: |
| 286 explicit WeakPtrFactory(T* ptr) : ptr_(ptr) { | 329 explicit WeakPtrFactory(T* ptr) |
| 287 } | 330 : WeakPtrFactoryBase(reinterpret_cast<uintptr_t>(ptr)) {} |
| 288 | 331 |
| 289 ~WeakPtrFactory() { ptr_ = nullptr; } | 332 ~WeakPtrFactory() {} |
| 290 | 333 |
| 291 WeakPtr<T> GetWeakPtr() { | 334 WeakPtr<T> GetWeakPtr() { |
| 292 DCHECK(ptr_); | 335 DCHECK(ptr_); |
| 293 return WeakPtr<T>(weak_reference_owner_.GetRef(), ptr_); | 336 return WeakPtr<T>(weak_reference_owner_.GetRef(), |
| 337 reinterpret_cast<T*>(ptr_)); | |
| 294 } | 338 } |
| 295 | 339 |
| 296 // Call this method to invalidate all existing weak pointers. | 340 // Call this method to invalidate all existing weak pointers. |
| 297 void InvalidateWeakPtrs() { | 341 void InvalidateWeakPtrs() { |
| 298 DCHECK(ptr_); | 342 DCHECK(ptr_); |
| 299 weak_reference_owner_.Invalidate(); | 343 weak_reference_owner_.Invalidate(); |
| 300 } | 344 } |
| 301 | 345 |
| 302 // Call this method to determine if any weak pointers exist. | 346 // Call this method to determine if any weak pointers exist. |
| 303 bool HasWeakPtrs() const { | 347 bool HasWeakPtrs() const { |
| 304 DCHECK(ptr_); | 348 DCHECK(ptr_); |
| 305 return weak_reference_owner_.HasRefs(); | 349 return weak_reference_owner_.HasRefs(); |
| 306 } | 350 } |
| 307 | 351 |
| 308 private: | 352 private: |
| 309 internal::WeakReferenceOwner weak_reference_owner_; | |
| 310 T* ptr_; | |
| 311 DISALLOW_IMPLICIT_CONSTRUCTORS(WeakPtrFactory); | 353 DISALLOW_IMPLICIT_CONSTRUCTORS(WeakPtrFactory); |
| 312 }; | 354 }; |
| 313 | 355 |
| 314 // A class may extend from SupportsWeakPtr to let others take weak pointers to | 356 // A class may extend from SupportsWeakPtr to let others take weak pointers to |
| 315 // it. This avoids the class itself implementing boilerplate to dispense weak | 357 // it. This avoids the class itself implementing boilerplate to dispense weak |
| 316 // pointers. However, since SupportsWeakPtr's destructor won't invalidate | 358 // pointers. However, since SupportsWeakPtr's destructor won't invalidate |
| 317 // weak pointers to the class until after the derived class' members have been | 359 // weak pointers to the class until after the derived class' members have been |
| 318 // destroyed, its use can lead to subtle use-after-destroy issues. | 360 // destroyed, its use can lead to subtle use-after-destroy issues. |
| 319 template <class T> | 361 template <class T> |
| 320 class SupportsWeakPtr : public internal::SupportsWeakPtrBase { | 362 class SupportsWeakPtr : public internal::SupportsWeakPtrBase { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 352 // base::WeakPtr<Derived> ptr = derived.AsWeakPtr(); // Fails. | 394 // base::WeakPtr<Derived> ptr = derived.AsWeakPtr(); // Fails. |
| 353 | 395 |
| 354 template <typename Derived> | 396 template <typename Derived> |
| 355 WeakPtr<Derived> AsWeakPtr(Derived* t) { | 397 WeakPtr<Derived> AsWeakPtr(Derived* t) { |
| 356 return internal::SupportsWeakPtrBase::StaticAsWeakPtr<Derived>(t); | 398 return internal::SupportsWeakPtrBase::StaticAsWeakPtr<Derived>(t); |
| 357 } | 399 } |
| 358 | 400 |
| 359 } // namespace base | 401 } // namespace base |
| 360 | 402 |
| 361 #endif // BASE_MEMORY_WEAK_PTR_H_ | 403 #endif // BASE_MEMORY_WEAK_PTR_H_ |
| OLD | NEW |