vtkObjectBase类
vtkObjectBase类是所有引用计数类的基类,其内部使用了原子(atomic)操作的引用计数ReferenceCount和vtkWeakPointerBase类型的WeakPointers(弱指针列表);
vtkObjectBase类执行引用计数:只要另一个对象使用它们,引用计数的对象就存在。一旦对引用计数对象的最后一个引用被删除,该对象将自发销毁。
vtkObjectBase类将构造函数和析构函数访问权限设置为protected,只供派生类的New方法和Delete方法使用;由于外部不可以访问构造函数和析构函数,则就不会在堆栈外自动生成vtkObjectBase类对象;
为什么要使用引用计数?
在程序中,一个值可能被用于多个对象,出现多个相同内容的对象,那么在程序中没必要将这个值或者对象存储很多次。能想到的办法是只保持一个拥有值的对象,其他对象共享这个值对象的副本;引用计数就是在做这个事情,它允许多个有相同值的对象共享这个值,构建一个简单的垃圾回收机制,只要其他对象引用某对象(对象O),对象O就会增加一个引用计数,随着其他对象的析构消亡,对象O就会减少一个引用计数,如果最后引用对象O的对象移除,对象O就会自动析构。
VTK里使用引用计数的好处是,可以实现数据之间的共享而不用复制,从而达到节省内存的目的;
成员变量
vtkAtomicInt32 ReferenceCount;
vtkWeakPointerBase **WeakPointers;
WeakPointers用于记录弱指针列表;
方法
获取类名的字符串:
virtual const char* GetClassNameInternal() const { return "vtkObjectBase"; }
const char* GetClassName() const;
判断字符串描述的类型与当前类类型是否相同:
static vtkTypeBool IsTypeOf(const char* name);
virtual vtkTypeBool IsA(const char* name);
判断输入类型与基类的代数:
static vtkIdType GetNumberOfGenerationsFromBaseType(const char* name);
virtual vtkIdType GetNumberOfGenerationsFromBase(const char* name);
创建和释放:
New用于创建对象,Delete用于释放对象;一般情况下不要使用FastDelete;
virtual void Delete();
virtual void FastDelete();
static vtkObjectBase* New() {
vtkObjectBase* o = new vtkObjectBase;
o->InitializeObjectBase();
return o;
}
void InitializeObjectBase();
打印日志:
void Print(ostream& os);
virtual void PrintSelf(ostream& os, vtkIndent indent);
virtual void PrintHeader(ostream& os, vtkIndent indent);
virtual void PrintTrailer(ostream& os, vtkIndent indent);
Print调用了PrintHeader、PrintSelf和PrintTrailer;
void vtkObjectBase::Print(ostream& os) {
vtkIndent indent;
this->PrintHeader(os, vtkIndent(0));
this->PrintSelf(os, indent.GetNextIndent());
this->PrintTrailer(os, vtkIndent(0));
}
PrintHeader用于打印当前类名:
void vtkObjectBase::PrintHeader(ostream& os, vtkIndent indent) {
os << indent << this->GetClassName() << " (" << this << ")\n";
}
PrintSelf用于打印引用计数:
void vtkObjectBase::PrintSelf(ostream& os, vtkIndent indent) {
os << indent << "Reference Count: " << this->ReferenceCount << "\n";
}
PrintTrailer用于打印每个层次的缩进(空格字符串):
void vtkObjectBase::PrintTrailer(ostream& os, vtkIndent indent) {
os << indent << "\n";
}
vtkIndent类使用了一个含有40个空格的全局静态变量blanks,vtkIndent重载了operator<<,可以根据Indent在blanks定位字符串开始位置;
ostream& operator<<(ostream& os, const vtkIndent& ind) {
os << blanks + (VTK_NUMBER_OF_BLANKS - ind.Indent);
return os;
}
引用计数的核心接口
下面是对外使用的接口:
virtual void Register(vtkObjectBase* o);
virtual void UnRegister(vtkObjectBase* o);
int GetReferenceCount() { return this->ReferenceCount; }
void SetReferenceCount(int);
这里需要注意的是,如果是使用下面的代码New了一个指针时,之后调用GetReferenceCount函数后,得到的结果不一定为1;
T* ptr = vtk**::New();
Register和UnRegister是调用了内部的protected函数:
virtual void RegisterInternal(vtkObjectBase*, vtkTypeBool check);
virtual void UnRegisterInternal(vtkObjectBase*, vtkTypeBool check);
virtual void ReportReferences(vtkGarbageCollector*);
具体实现如下:
void vtkObjectBase::RegisterInternal(vtkObjectBase*, vtkTypeBool check){
// If a reference is available from the garbage collector, use it.
// Otherwise create a new reference by incrementing the reference
// count.
if (!(check && vtkObjectBaseToGarbageCollectorFriendship::TakeReference(this))){
this->ReferenceCount++;
}
}
//----------------------------------------------------------------------------
void vtkObjectBase::UnRegisterInternal(vtkObjectBase*, vtkTypeBool check){
// If the garbage collector accepts a reference, do not decrement
// the count.
if (check && this->ReferenceCount > 1 &&
vtkObjectBaseToGarbageCollectorFriendship::GiveReference(this)) {
return;
}
// Decrement the reference count, delete object if count goes to zero.
if (--this->ReferenceCount <= 0) {
// Clear all weak pointers to the object before deleting it.
if (this->WeakPointers) {
vtkWeakPointerBase** p = this->WeakPointers;
while (*p) {
vtkObjectBaseToWeakPointerBaseFriendship::ClearPointer(*p++);
}
delete[] this->WeakPointers;
}
delete this;
}
else if (check)
{
// The garbage collector did not accept the reference, but the
// object still exists and is participating in garbage collection.
// This means either that delayed garbage collection is disabled
// or the collector has decided it is time to do a check.
vtkGarbageCollector::Collect(this);
}
}
vtkObjectBaseToGarbageCollectorFriendship只是vtkGarbageCollector的warp类:
class vtkObjectBaseToGarbageCollectorFriendship {
public:
static int GiveReference(vtkObjectBase* obj) { return vtkGarbageCollector::GiveReference(obj); }
static int TakeReference(vtkObjectBase* obj) { return vtkGarbageCollector::TakeReference(obj); }
};
vtkWeakPointerBaseToObjectBaseFriendship是vtkWeakPointerBase类的warp类:
class vtkWeakPointerBaseToObjectBaseFriendship
{
public:
static void AddWeakPointer(vtkObjectBase* r, vtkWeakPointerBase* p);
static void RemoveWeakPointer(vtkObjectBase* r, vtkWeakPointerBase* p) noexcept;
static void ReplaceWeakPointer(
vtkObjectBase* r, vtkWeakPointerBase* bad, vtkWeakPointerBase* good) noexcept;
};