WeakPtr 学习

来源:互联网 发布:手机连接电视同一网络 编辑:程序博客网 时间:2024/06/05 04:18
/*一、说明WeakPtr,可用来在不同线程间传递对象。二、相关类Flag : public RefCountedThreadSafe<Flag>-->标志类,自身是有"线程安全引用计数"的。用来标志WeakPtr所指向的对象是否还可用IsValid()。WeakReference-->含有一个scoped_refptr<const Flag> flag,对应Flag的一个引用WeakPtrBase-->作为WeakPtr的父类存在,它体内含有WeakReference ref_,实际上就是为了让WeakPtr体内包含一个WeakReference对象,更进一步,就是为了让WeakPtr对象拥有一个Flag对象引用。WeakReferenceOwner-->负责new出Flag对象,保证所有从本类请求的Flag对象都是同一个,而同一个Flag对象代表了同一个object指针WeakPtr : public WeakPtrBase -->这样的话,WeakPtr也就有了WeakReference对象,进而有了一个Flag对象。WeakPtr析构时,就引起Flag的引用-1 WeakPtrFactory-->WeakPtr的生产工厂,体内有一个WeakReferenceOwner,通过它来生产WeakPtr。三、原理对象要跨线程,比如说线程1有一个对象A通过指针将对象传递给线程2,线程2怕的是在用的时候,那个对象A被释放了。而如果能有一个地方查到此对象是否还存在的话,跨线程就ok了。假设有对象指针TFlag对象就是用来标志那个对象T是否还存在的标志。WeakReferenceOwner只能产生针对T的WeakReference(同一个Flag构成的)由于Flag是new出来的,它的析构不是由外力决定的,而是由它被引用的情况决定的,因为它是"可引用计数"的。引用计数归0后自然就是释放内存。所以Flag寿命比object长一些,与最后一个WeakPtr一起结束生命。每个WeakReference是Flag的一份引用,而每个WeakPtr中有一个WeakReference当WeakPtr析构时,WeakReference就析构了,最终引起Flag引用数量-=1,当引用数量==0时,Flag析构,也就是说在所有WeakPtr析构前,Flag是不会析构的,这个对象可被任何关于T的WeakPtr用来查询,T是否有效构建过程是同一个WeakReferenceOwner用同一个Flag来构建WeakPtr的,所以所有WeakPtr都指向同一个对象。 */#ifndef BASE_MEMORY_WEAK_PTR_H_#define BASE_MEMORY_WEAK_PTR_H_namespace base {template <typename T> class SupportsWeakPtr;template <typename T> class WeakPtr;namespace internal {class Flag : public RefCountedThreadSafe<Flag> {public:Flag();void Invalidate();// is_valid_ = false;bool IsValid() const;//是否可用void DetachFromThread() { thread_checker_.DetachFromThread(); }private:friend class base::RefCountedThreadSafe<Flag>;~Flag();ThreadChecker thread_checker_;bool is_valid_;};//Flagclass BASE_EXPORT WeakReference {public:WeakReference();explicit WeakReference(const Flag* flag);~WeakReference();bool is_valid() const;private:scoped_refptr<const Flag> flag_;//scoped};//WeakReferenceclass BASE_EXPORT WeakReferenceOwner {public:WeakReferenceOwner();~WeakReferenceOwner();WeakReference GetRef() const;//只返回唯一Flagbool HasRefs() const {return flag_.get() && !flag_->HasOneRef();}void Invalidate();//flag_->Invalidate(),flag=null// Indicates that this object will be used on another thread from now on.//valid_thread_id_ = kInvalidThreadId=0;void DetachFromThread() {if (flag_) flag_->DetachFromThread();}private:mutable scoped_refptr<WeakReference::Flag> flag_;};// This class simplifies the implementation of WeakPtr's type conversion// constructor by avoiding the need for a public accessor for ref_.  A// WeakPtr<T> cannot access the private members of WeakPtr<U>, so this// base class gives us a way to access ref_ in a protected fashion.class BASE_EXPORT WeakPtrBase {//WeakPtr父类,封装WeakReferencepublic:WeakPtrBase();~WeakPtrBase();protected:explicit WeakPtrBase(const WeakReference& ref);WeakReference ref_;};// This class provides a common implementation of common functions that would// otherwise get instantiated separately for each distinct instantiation of// SupportsWeakPtr<>.class SupportsWeakPtrBase {public:// A safe static downcast of a WeakPtr<Base> to WeakPtr<Derived>. This// conversion will only compile if there is exists a Base which inherits// from SupportsWeakPtr<Base>. See base::AsWeakPtr() below for a helper// function that makes calling this easier.// WeakPtr<Base>  WeakPtr<Derived>间转换// 父类继承了SupportsWeakPtr,子类继承了父类,见下面helper函数template<typename Derived>static WeakPtr<Derived> StaticAsWeakPtr(Derived* t) {typedefis_convertible<Derived, internal::SupportsWeakPtrBase&> convertible;COMPILE_ASSERT(convertible::value,AsWeakPtr_argument_inherits_from_SupportsWeakPtr);//只提供了一个模板参数,另一个没有,需要编译器自己推导return AsWeakPtrImpl<Derived>(t, *t);}private:// This template function uses type inference to find a Base of Derived// which is an instance of SupportsWeakPtr<Base>. We can then safely// static_cast the Base* to a Derived*.// 类型推导,找出父类子所含有的ptr,然后将其转成子类的ptr,然后再封装成// WeakPtr返回回去。//用参数约束出了父类的名字template <typename Derived, typename Base>static WeakPtr<Derived> AsWeakPtrImpl(Derived* t, const SupportsWeakPtr<Base>&){WeakPtr<Base> ptr = t->Base::AsWeakPtr();return WeakPtr<Derived>(ptr.ref_, static_cast<Derived*>(ptr.ptr_));}};}  // namespace internaltemplate <typename T> class WeakPtrFactory;// The WeakPtr class holds a weak reference to |T*|.//// This class is designed to be used like a normal pointer.  You should always// null-test an object of this class before using it or invoking a method that// may result in the underlying object being destroyed.//// EXAMPLE:////   class Foo { ... };//   WeakPtr<Foo> foo;//   if (foo)//     foo->method();//template <typename T>class WeakPtr : public internal::WeakPtrBase {public:WeakPtr() : ptr_(NULL) {}// Allow conversion from U to T provided U "is a" T.template <typename U>WeakPtr(const WeakPtr<U>& other) : WeakPtrBase(other), ptr_(other.get()) {}T* get() const { return ref_.is_valid() ? ptr_ : NULL; }operator T*() const { return get(); }T& operator*() const {DCHECK(get() != NULL);return *get();}T* operator->() const {DCHECK(get() != NULL);return get();}void reset() {ref_ = internal::WeakReference();ptr_ = NULL;}private:friend class internal::SupportsWeakPtrBase;friend class SupportsWeakPtr<T>;friend class WeakPtrFactory<T>;WeakPtr(const internal::WeakReference& ref, T* ptr): WeakPtrBase(ref),ptr_(ptr) {}// This pointer is only valid when ref_.is_valid() is true.  Otherwise, its// value is undefined (as opposed to NULL).T* ptr_;};// A class may extend from SupportsWeakPtr to expose weak pointers to itself.// This is useful in cases where you want others to be able to get a weak// pointer to your class.  It also has the property that you don't need to// initialize it from your constructor.template <class T>class SupportsWeakPtr : public internal::SupportsWeakPtrBase {public:SupportsWeakPtr() {}WeakPtr<T> AsWeakPtr() {return WeakPtr<T>(weak_reference_owner_.GetRef(), static_cast<T*>(this));}// Indicates that this object will be used on another thread from now on.void DetachFromThread() {weak_reference_owner_.DetachFromThread();}protected:~SupportsWeakPtr() {}private:internal::WeakReferenceOwner weak_reference_owner_;DISALLOW_COPY_AND_ASSIGN(SupportsWeakPtr);};// Helper function that uses type deduction to safely return a WeakPtr<Derived>// when Derived doesn't directly extend SupportsWeakPtr<Derived>, instead it// extends a Base that extends SupportsWeakPtr<Base>.//// EXAMPLE://   class Base : public base::SupportsWeakPtr<Producer> {};//   class Derived : public Base {};////   Derived derived;//   base::WeakPtr<Derived> ptr = base::AsWeakPtr(&derived);//// Note that the following doesn't work (invalid type conversion) since// Derived::AsWeakPtr() is WeakPtr<Base> SupportsWeakPtr<Base>::AsWeakPtr(),// and there's no way to safely cast WeakPtr<Base> to WeakPtr<Derived> at// the caller.////   base::WeakPtr<Derived> ptr = derived.AsWeakPtr();  // Fails.//  在这种情况下,子类中的AsWeakPtr()函数不是WeakPtr<Derived>类型的,而是//  WeakPtr<Producer> SupportsWeakPtr<Base>::AsWeakPtr()类型的,因为子类中的内//容是继承自父类的,所以,不能直接调用那句话。 父子类形成的模板,不再兼容//  也就是想要WeakPtr<Derived>  而返回的是WeakPtr<Base>////  需要调用internal::SupportsWeakPtrBase::StaticAsWeakPtr<Derived>(t)转换template <typename Derived>WeakPtr<Derived> AsWeakPtr(Derived* t) {return internal::SupportsWeakPtrBase::StaticAsWeakPtr<Derived>(t);}// A class may alternatively be composed of a WeakPtrFactory and thereby// control how it exposes weak pointers to itself.  This is helpful if you only// need weak pointers within the implementation of a class.  This class is also// useful when working with primitive types.  For example, you could have a// WeakPtrFactory<bool> that is used to pass around a weak reference to a bool.// 工厂是对owner是封装template <class T>class WeakPtrFactory {public:explicit WeakPtrFactory(T* ptr) : ptr_(ptr) {}~WeakPtrFactory() {ptr_ = NULL;}WeakPtr<T> GetWeakPtr() {DCHECK(ptr_);return WeakPtr<T>(weak_reference_owner_.GetRef(), ptr_);}// Call this method to invalidate all existing weak pointers.void InvalidateWeakPtrs() {//让所有弱指针无效DCHECK(ptr_);weak_reference_owner_.Invalidate();}// Call this method to determine if any weak pointers exist.bool HasWeakPtrs() const {DCHECK(ptr_);return weak_reference_owner_.HasRefs();}// Indicates that this object will be used on another thread from now on.void DetachFromThread() {DCHECK(ptr_);weak_reference_owner_.DetachFromThread();}private:internal::WeakReferenceOwner weak_reference_owner_;T* ptr_;DISALLOW_IMPLICIT_CONSTRUCTORS(WeakPtrFactory);};}  // namespace base/*    上面提供了两种方法,让一个类可导出WeakPtr指针。一种是将WeakPtrFactory包装到类定义中,工厂方法,一种是继承SupportsWeakPtr*/#endif  // BASE_MEMORY_WEAK_PTR_H_/*  模板在用父子类特化后不再兼容template <class T>class WeakPtr{};template <class T>class SupportsWeakPtr{public:WeakPtr<T> AsWeakPtr() {return WeakPtr<T>;}}; class Base:public SupportsWeakPtr<Base>{};class Derived:public Base{};int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]){Derived derived;//error C2440: “初始化”: 无法从“WeakPtr<T>”转换为“WeakPtr<T>”//WeakPtr<Derived> ptr = derived.AsWeakPtr();WeakPtr<Base> pb;WeakPtr<Derived> pd;// error C2679: 二进制“=”: 没有找到接受“WeakPtr<T>”//类型的右操作数的运算符(或没有可接受的转换)//pb=pd;//error C2440: “初始化”: 无法从“WeakPtr<T> *”转换为“WeakPtr<T> *”//WeakPtr<Base> *p= new WeakPtr<Derived>;system("pause");return 0;}*/