现在的位置: 首页 > 综合 > 正文

Open Scene Graph 内存管理

2013年08月27日 ⁄ 综合 ⁄ 共 1836字 ⁄ 字号 评论关闭

在Osg中有一个类被使用的最多,那就是ref_ptr.Osg中提供了一种自动管理内存的机制,这种机制涉及到两个类:第一个就是ref_ptr,另外一个就是osg::Referenced.

osg::Reference支持通过引用计数的方式来控制自己的生命周期,它期望,每次被一个新客户引用的时候,新客户能给他添加引用计数;而当客户不需要再使用它的时候,希望客户能够减少引用计数.

如果引用计数达到0,那么osg::Reference就会析构自己,释放内存.

但是这个过程对客户要求比较高,谁能记得住每次都添加引用和减少引用呢? ref_ptr能!这也是它为什么存在的原因.ref_ptr重载了大量的操作符来实现这个添加引用和减少引用的过程.

下面是一个使用ref_ptr的基本原则:

1.如果希望用ref_ptr来管理内存,你的类需要继承osg::Referenced

2.如果你的类的对象想要持有一个osg::Referenced的派生类的指针,你应该持有一个ref_ptr然后,让ref_ptr来持有一个指针

3.如果你只是在一个函数中短时间的使用一个osg::Referenced的派生类的指针,你不需要使用ref_ptr,直接用就可以了.如果你在短时间使用后,会传递给其他的对象来持有这个指针,你也不需要用ref_ptr,因为通过ref_ptr来长时间持有这个对象是其他的对象的责任了.

4.如果有两个类都从osg::Referenced派生,而你想继承这两个类,那就有麻烦了。Osg中的派生都没有用virtual修饰符,所以你的类对象中会出现两份osg::Referenced的东西.ref_ptr实际上不知道该怎么处理了.如果是一个严格的编译器,编译器甚至会报错!.这个时候,你必须做出选择,从其中一个派生,而另一个则采用组合的方式来处理.多继承就是这一点不好.不过话说回来,在代码中应该尽量不使用多继承,除非是从完全没有成员的纯抽象类继承(纯抽象类当做接口用).

下面来一段ref_ptr的代码看看:

inline ref_ptr& operator = (T* ptr)
{
if (_ptr==ptr) return *this;
T* tmp_ptr = _ptr;
_ptr = ptr;
if (_ptr) _ptr->ref();
// unref second to prevent any deletion of any object which might
// be referenced by the other object. i.e rp is child of the
// original _ptr.
if (tmp_ptr) tmp_ptr->unref();
return *this;
}

在给ref_ptr赋值的时候,它首先把新对象给ref一下,然后把原来的对象给unref一下.这个持续比较重要,如果反过来写就不行了.你想想看,如果我把同一个指针给它两次,如果反过来写,对象就会被销毁了! 然后是Referenced的代码:

inline void Referenced::ref() const
{
#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
++_refCount;
#else
if (_refMutex)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(*_refMutex);
++_refCount;
}
else
{
++_refCount;
}
#endif
}
inline void Referenced::unref() const
{
#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
bool needDelete = (--_refCount == 0);
#else
bool needDelete = false;
if (_refMutex)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(*_refMutex);
--_refCount;
needDelete = _refCount<=0;
}
else
{
--_refCount;
needDelete = _refCount<=0;
}
#endif
if (needDelete)
{
if (getDeleteHandler()) deleteUsingDeleteHandler();
else delete this;
}
}

去掉多线程控制的代码,其原理是很好理解的.

【上篇】
【下篇】

抱歉!评论已关闭.