目前我已经使用以下方法获得了一些引用计数类:
class RefCounted { public: void IncRef() { ++refCnt; } void DecRef() { if(!--refCnt)delete this; } protected: RefCounted():refCnt(0){} private: unsigned refCnt; //not implemented RefCounted(RefCounted&); RefCounted& operator = (RefCounted&}; };
我还有一个处理引用计数的智能指针类,虽然它没有统一使用(例如,在一两位性能关键代码中,我最小化了IncRef和DecRef调用的数量).
template<class T>class RefCountedPtr { public: RefCountedPtr(T *p) :p(p) { if(p)p->IncRef(); } ~RefCountedPtr() { if(p)p->DecRef(); } RefCountedPtr<T>& operator = (T *newP) { if(newP)newP->IncRef(); if(p) p ->DecRef(); p = newP; return *this; } RefCountedPtr<T>& operator = (RefCountedPtr<T> &newP) { if(newP.p)newP.p->IncRef(); if(p) p ->DecRef(); p = newP.p; return *this; } T& operator *() { return *p; } T* operator ->() { return p; } //comparison operators etc and some const versions of the above... private: T *p; };
对于类本身的一般用途,我打算使用读写器锁定系统,但是我真的不想为每一个IncRef和DecRef调用获取一个写入器锁.
我还想到了在IncRef调用之前指针可能无效的情况,请考虑:
class Texture : public RefCounted { public: //...varIoUs operations... private: Texture(const std::string &file) { //...load texture from file... TexPool.insert(this); } virtual ~Texture() { TexPool.erase(this); } freind CreateTextureFromFile; }; Texture *CreateTexture(const std::string &file) { TexPoolIterator i = TexPool.find(file); if(i != TexPool.end())return *i; else return new Texture(file); }
ThreadA ThreadB t = CreateTexture("ball.png"); t->IncRef(); ...use t... t2 = CreateTexture("ball.png");//returns *t ... thread suspended... t->DecRef();//deletes t ... ... t2->IncRef();//ERROR
所以我想我需要完全改变引用计数模型,我在设计中返回后添加引用的原因是为了支持以下内容:
MyObj->GetSomething()->GetSomethingElse()->DoSomething();
而不是必须:
SomeObject a = MyObj->GetSomething(); AnotherObject *b = a->GetSomethingElse(); b->DoSomething(); b->DecRef(); a->DecRef();
解决方法
使引用计数为原子,您将不需要任何锁定.在Windows :: InterlockedIncrement和:: InterlockedDecrement可以使用.在C 0x中,您有原子<> ;.