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

Unified Diff: base/memory/ref_counted.h

Issue 2451123004: WIP - allow scoped_refptr to be used without full defn of T (Closed)
Patch Set: Created 4 years, 2 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | base/win/scoped_comptr.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 6a689388d9d2d93ea0f1624c2316bdbadf044907..acbe67583221c5dad76393d2abab835f94acb7f3 100644
--- a/base/memory/ref_counted.h
+++ b/base/memory/ref_counted.h
@@ -269,17 +269,29 @@ class scoped_refptr {
public:
typedef T element_type;
+ // RefCounted<T> or RefCountedThreadSafe<T> depending on the type implemented
+ // by T (or T itself for RefCountedThreadSafe<T, CustomTraits> and the rare
+ // use case of classes providing their own AddRef/Release methods and being
+ // stored in a scoped_refptr).
+ using RefCountedType = typename std::conditional<
+ std::is_convertible<T*, base::RefCounted<T>*>::value,
+ base::RefCounted<T>,
+ typename std::conditional<
+ std::is_convertible<T*, base::RefCountedThreadSafe<T>*>::value,
+ base::RefCountedThreadSafe<T>,
+ T>::type>::type;
+
scoped_refptr() = default;
scoped_refptr(T* p) : ptr_(p) {
- if (ptr_)
- AddRef(ptr_);
+ if (ref_)
+ AddRef(ref_);
}
// Copy constructor.
scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
- if (ptr_)
- AddRef(ptr_);
+ if (ref_)
+ AddRef(ref_);
}
// Copy conversion constructor.
@@ -287,8 +299,8 @@ class scoped_refptr {
typename = typename std::enable_if<
std::is_convertible<U*, T*>::value>::type>
scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) {
- if (ptr_)
- AddRef(ptr_);
+ if (ref_)
+ AddRef(ref_);
}
// Move constructor. This is required in addition to the conversion
@@ -304,8 +316,8 @@ class scoped_refptr {
}
~scoped_refptr() {
- if (ptr_)
- Release(ptr_);
+ if (ref_)
+ Release(ref_);
}
T* get() const { return ptr_; }
@@ -322,12 +334,14 @@ class scoped_refptr {
scoped_refptr<T>& operator=(T* p) {
// AddRef first so that self assignment should work
+ // Note: This AddRef() can't use the |ref_| trick, so assigning from a naked
+ // pointer requires the assignor to have the full definition of |T|.
if (p)
AddRef(p);
- T* old_ptr = ptr_;
+ const RefCountedType* old_ref = ref_;
ptr_ = p;
- if (old_ptr)
- Release(old_ptr);
+ if (old_ref)
+ Release(old_ref);
return *this;
}
@@ -379,8 +393,22 @@ class scoped_refptr {
}
protected:
+ //FIXME need to update |ref_| when updating |ptr_|.
T* ptr_ = nullptr;
+ // |ref_| merely points to |ptr_| but the type checking is done when
+ // scoped_refptr is constructed instead of when it's used, this allows
+ // callsites that merely do:
+ // void PassRefToFoo(Foo* foo, scoped_refptr<T> t) {
+ // foo->TakeRef(std::move(t));
+ // }
+ // to compile without the full definition of |T| as they can perform
+ // AddRef/Release operations on it without having to know that it implements
+ // RefCountedInterface.
+ //FIXME: This still doesn't work because template instantiations still need to
+ //know the full type to derive |RefCountedType|...
+ const RefCountedType* ref_ = ptr_;
+
private:
// Friend required for move constructors that set r.ptr_ to null.
template <typename U>
@@ -390,18 +418,22 @@ class scoped_refptr {
// 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);
+ static void AddRef(const RefCountedType* ref_type);
+ static void Release(const RefCountedType* ref_type);
};
+// static
template <typename T>
-void scoped_refptr<T>::AddRef(T* ptr) {
- ptr->AddRef();
+void scoped_refptr<T>::AddRef(
+ const scoped_refptr<T>::RefCountedType* ref_type) {
+ ref_type->AddRef();
}
+// static
template <typename T>
-void scoped_refptr<T>::Release(T* ptr) {
- ptr->Release();
+void scoped_refptr<T>::Release(
+ const scoped_refptr<T>::RefCountedType* ref_type) {
+ ref_type->Release();
}
// Handy utility for creating a scoped_refptr<T> out of a T* explicitly without
« no previous file with comments | « no previous file | base/win/scoped_comptr.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698