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

Unified Diff: base/memory/ref_counted.h

Issue 2471043002: Allow icomplete types in scoped_refptr<T>. (Closed)
Patch Set: Release can delete this Created 4 years, 1 month 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | base/test/opaque_ref_counted.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/memory/ref_counted.h
diff --git a/base/memory/ref_counted.h b/base/memory/ref_counted.h
index 960c8a28453122a5e00a2cb72d5f420e7b642f15..c9ba42401ed43976aa3e0317d72906cc81e612ab 100644
--- a/base/memory/ref_counted.h
+++ b/base/memory/ref_counted.h
@@ -271,41 +271,46 @@ class scoped_refptr {
scoped_refptr() {}
- scoped_refptr(T* p) : ptr_(p) {
+ scoped_refptr(T* p) : ptr_(p), ptr_caller_(&PtrCallerImpl) {
if (ptr_)
- AddRef(ptr_);
+ ptr_caller_(ptr_, PtrCall::AddRef);
}
// Copy constructor.
- scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
+ scoped_refptr(const scoped_refptr<T>& r)
+ : ptr_(r.ptr_), ptr_caller_(r.ptr_caller_) {
if (ptr_)
- AddRef(ptr_);
+ ptr_caller_(ptr_, PtrCall::AddRef);
}
// Copy conversion constructor.
template <typename U,
typename = typename std::enable_if<
std::is_convertible<U*, T*>::value>::type>
- scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) {
+ scoped_refptr(const scoped_refptr<U>& r)
+ : ptr_(r.get()), ptr_caller_(&PtrCallerImpl) {
if (ptr_)
- AddRef(ptr_);
+ ptr_caller_(ptr_, PtrCall::AddRef);
}
// Move constructor. This is required in addition to the conversion
// constructor below in order for clang to warn about pessimizing moves.
- scoped_refptr(scoped_refptr&& r) : ptr_(r.get()) { r.ptr_ = nullptr; }
+ scoped_refptr(scoped_refptr&& r) : ptr_(r.get()), ptr_caller_(r.ptr_caller_) {
+ r.ptr_ = nullptr;
+ }
// Move conversion constructor.
template <typename U,
typename = typename std::enable_if<
std::is_convertible<U*, T*>::value>::type>
- scoped_refptr(scoped_refptr<U>&& r) : ptr_(r.get()) {
+ scoped_refptr(scoped_refptr<U>&& r)
+ : ptr_(r.get()), ptr_caller_(&PtrCallerImpl) {
r.ptr_ = nullptr;
}
~scoped_refptr() {
if (ptr_)
- Release(ptr_);
+ ptr_caller_(ptr_, PtrCall::Release);
}
T* get() const { return ptr_; }
@@ -321,23 +326,19 @@ class scoped_refptr {
}
scoped_refptr<T>& operator=(T* p) {
- // AddRef first so that self assignment should work
- if (p)
- AddRef(p);
- T* old_ptr = ptr_;
- ptr_ = p;
- if (old_ptr)
- Release(old_ptr);
+ Assign(p, &PtrCallerImpl);
return *this;
}
scoped_refptr<T>& operator=(const scoped_refptr<T>& r) {
- return *this = r.ptr_;
+ Assign(r.ptr_, r.ptr_caller_);
+ return *this;
}
template <typename U>
scoped_refptr<T>& operator=(const scoped_refptr<U>& r) {
- return *this = r.get();
+ Assign(r.get(), &PtrCallerImpl);
+ return *this;
}
scoped_refptr<T>& operator=(scoped_refptr<T>&& r) {
@@ -354,11 +355,13 @@ class scoped_refptr {
void swap(T** pp) {
T* p = ptr_;
ptr_ = *pp;
+ ptr_caller_ = &PtrCallerImpl;
*pp = p;
}
void swap(scoped_refptr<T>& r) {
- swap(&r.ptr_);
+ std::swap(ptr_, r.ptr_);
+ std::swap(ptr_caller_, r.ptr_caller_);
}
explicit operator bool() const { return ptr_ != nullptr; }
@@ -379,33 +382,41 @@ class scoped_refptr {
}
protected:
+ enum class PtrCall { AddRef, Release };
+ using PtrCallerFunction = void (*)(T* ptr, PtrCall call);
+
+ static void PtrCallerImpl(T* ptr, PtrCall call) {
+ switch (call) {
+ case PtrCall::AddRef:
+ ptr->AddRef();
+ break;
+ case PtrCall::Release:
+ ptr->Release();
+ break;
+ }
+ }
+
T* ptr_ = nullptr;
+ PtrCallerFunction ptr_caller_ = nullptr;
private:
- // Friend required for move constructors that set r.ptr_ to null.
template <typename U>
friend class scoped_refptr;
- // Non-inline helpers to allow:
- // class Opaque;
- // extern template class scoped_refptr<Opaque>;
- // Otherwise the compiler will complain that Opaque is an incomplete type.
- static void AddRef(T* ptr);
- static void Release(T* ptr);
+ void Assign(T* p, PtrCallerFunction caller) {
+ // AddRef first so that self assignment should work
+ if (p)
+ caller(p, PtrCall::AddRef);
+ T* old_ptr = ptr_;
+ PtrCallerFunction old_caller = ptr_caller_;
+ ptr_ = p;
+ ptr_caller_ = caller;
+ if (old_ptr)
+ old_caller(old_ptr, PtrCall::Release);
+ // Release above can potentially delete this object
+ }
};
-// static
-template <typename T>
-void scoped_refptr<T>::AddRef(T* ptr) {
- ptr->AddRef();
-}
-
-// static
-template <typename T>
-void scoped_refptr<T>::Release(T* ptr) {
- ptr->Release();
-}
-
// Handy utility for creating a scoped_refptr<T> out of a T* explicitly without
// having to retype all the template arguments
template <typename T>
« no previous file with comments | « no previous file | base/test/opaque_ref_counted.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698