osg.Referenced 是 OpenSceneGraph 中所有引用计数对象的基类。引用计数对象是指其生命周期由多个引用对象共同管理,通过增减引用计数来控制对象的释放时机。
class OSG_EXPORT Referenced: public Object
{
//...
}
其中,Object 为 OSG 中所有对象的基类,包含了一些基础的功能和接口。
osg.Referenced 中的引用计数机制是通过两个主要的成员变量来实现的:
AtomicInt _refCount; // 引用计数
bool _deleteOnZeroRefCount; // 引用计数在降为 0 时是否自动销毁对象
其中,_refCount 是一个原子计数器对象,可以确保多线程环境下的并发修改安全;_deleteOnZeroRefCount 标记了当对象的引用计数减为 0 时,是否自动销毁对象。
引用计数的增减分别通过以下接口实现:
void osg::Referenced::ref() const // 引用计数增加
bool osg::Referenced::unref() const // 引用计数减少,如果引用计数为 0 则自动销毁对象
int osg::Referenced::referenceCount() const // 返回当前对象的引用计数
其中,ref() 操作应当在获取该对象的“读取”引用时调用;而 unref() 操作应当在释放该对象的引用时调用。如需在单线程环境下处理引用计数,可以根据实际情况直接使用 referenceCount() 接口对引用计数进行监控。
为了使用引用计数机制,所有 osg.Referenced 的子类需要重载 cloneType() 和 clone() 接口。
virtual Object* cloneType() const { return new MyClass(); }
virtual Object* clone(const CopyOp&) const { return new MyClass(*this); }
cloneType() 必须返回一个“相同类型的新对象”的实例,而 clone() 则必须返回一个“完全拷贝自身”的实例,其中 CopyOp 为拷贝操作的附加参数,用于确定拷贝的深度和方式等。
由于引用计数机制的存在,当多个对象互相关联时,应当避免循环引用,以免导致内存泄漏。(如 A 引用 B,B 又反向引用了 A)
osg.Referenced 不会对其成员变量进行自动的引用计数管理。因此,当成员变量是引用计数类型时,需要在对象的构造器和析构器中添加相应的 ref() 和 unref() 操作。(or 在构造函数中使用递归调用进行参考计数的递归处理)