class RefCountedBase {
protected:
RefCountedBase();
~RefCountedBase();
void AddRef();
// Returns true if the object should self-delete.
bool Release();
private:
int ref_count_;
#ifndef NDEBUG
bool in_dtor_;
#endif
DFAKE_MUTEX(add_release_);
DISALLOW_COPY_AND_ASSIGN(RefCountedBase);
};
RefCountedBase::RefCountedBase() : ref_count_(0) {
#ifndef NDEBUG
in_dtor_ = false;
#endif
}
RefCountedBase::~RefCountedBase() {
#ifndef NDEBUG
DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()";
#endif
}
void RefCountedBase::AddRef() {
// TODO(maruel): Add back once it doesn't assert 500 times/sec.
// Current thread books the critical section "AddRelease" without release it.
// DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_);
#ifndef NDEBUG
DCHECK(!in_dtor_);
#endif
++ref_count_;
}
bool RefCountedBase::Release() {
// TODO(maruel): Add back once it doesn't assert 500 times/sec.
// Current thread books the critical section "AddRelease" without release it.
// DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_);
#ifndef NDEBUG
DCHECK(!in_dtor_);
#endif
if (--ref_count_ == 0) {
#ifndef NDEBUG
in_dtor_ = true;
#endif
return true;
}
return false;
}
template <class T>
class RefCounted : public subtle::RefCountedBase {
public:
RefCounted() { }
~RefCounted() { }
void AddRef() {
subtle::RefCountedBase::AddRef();
}
void Release() {
if (subtle::RefCountedBase::Release()) {
delete static_cast<T*>(this);
}
}
private:
DISALLOW_COPY_AND_ASSIGN(RefCounted<T>);
};