Chromium Base - scoped_refptr、RefcountedKeyedService、RefCounted、RefCountedThreadedSafe

类名: template <class T> class scoped_refptr scoped_refptr<T>

定义了一个被管理的裸指针:  T* ptr_。


 在scoped_refptr<T>被构造时:

constexpr scoped_refptr(T* p) : ptr_(p) {
  if (ptr_)
   AddRef(ptr_); //<----
}

以向ptr_添加一个引用。关于AddRef,定义则是:

template <typename T>
void scoped_refptr<T>::AddRef(T* ptr) {
  ptr->AddRef();  //<----
}

这意味着,被管理的类<T>也一定要实现AddRef。同理Release也要实现。而在实际使用时,类也一般会继承RefcountedKeyedService之类的带有计数模板的类。

关于计数模板的相关内容后面再说,先看看哪些操作会导致计数的变化。


对于T而言,

1. 引用计数增长

scoped_refptr<T>构造

public

调用T->AddRef()

AddRef

private

调用T->AddRef()

多个scoped_refptr<T>引用同一个T
事实上就是多次调用了构造函数。而计数器存在T中,并不是scoped_refptr<>中,所以T的计数会随之增加
operator=(T* p)生成一个scoped_refptr<T>并赋值,构造的时候引用计数增加

2. 引用计数减少

scoped_refptr<T>析构

public

调用T->Release()

Release()

private

调用T->Release()

reset()

public

void reset() { scoped_refptr().swap(*this); }

在栈上临时构造一个空的scoped_refptr并转移当前的scoped_refptr到里面去。

当本函数退出时,scoped_refptr析构,计数减一

swap()

public

*是否析构视情况而定,reset()也是调用了swap()

3. 引用计数不变

get()public
Move Constructor
public
release()

public

首字母小写的release。释放所有权。

但是因为计数器存在T中,而不是scoped_refptr<>中,所以释放所有权并不会导致任何计数变化

RefcountedKeyedService的继承关系如下:

class RefcountedKeyedService : public base::RefCountedThreadSafe<RefcountedKeyedService,  impl::RefcountedKeyedServiceTraits>

对于RefCounted/RefCountedThreadedSafe来说,默认它会引用DefaultRefCountedTraits来进行清理工作。

template <class T, typename Traits>
class RefCounted;  //<-- RefCounted<T, Traits>


template <typename T>
struct DefaultRefCountedTraits {
  static void Destruct(const T* x) {
    RefCounted<T, DefaultRefCountedTraits>::DeleteInternal(x);
  }
};

template <class T, typename Traits = DefaultRefCountedTraits<T>>  //<--- DefaultRefCountedTraits
class RefCounted : public subtle::RefCountedBase {
...
}

而DefaultRefCountedTraits的工作很简单,直接delete:

  friend struct DefaultRefCountedTraits<T>;
  template <typename U>
  static void DeleteInternal(const U* x) {
    delete x;
  }

当然,它也支持自定义清理类,比如我们举例的RefcountedKeyedService使用了RefcountedKeyedServiceTraits,它是自定义删除类。阅读RefcountedKeyedServiceTraits::Destruct可以得知它的实现如下,一样,直接delete obj,不会清空指针为nullptr。

struct KEYED_SERVICE_EXPORT RefcountedKeyedServiceTraits {
  static void Destruct(const RefcountedKeyedService* obj);
};

void RefcountedKeyedServiceTraits::Destruct(const RefcountedKeyedService* obj) {
  if (obj->task_runner_ && !obj->task_runner_->RunsTasksInCurrentSequence()) {
    obj->task_runner_->DeleteSoon(FROM_HERE, obj);
  } else {
    delete obj; //<--------
  }
}