Improved the speed of the ValueObject get/setting by utilizing typeid() and static_cast<> in place of original dynamic_cast<>'s

This commit is contained in:
Robert Osfield 2016-02-04 13:10:28 +00:00
parent d8d37e3da7
commit b4eb8d4597
3 changed files with 83 additions and 9 deletions

View File

@ -170,6 +170,14 @@ class OSG_EXPORT Object : public Referenced
* Equivalent to dynamic_cast<const CallbackObject*>(this).*/
virtual const CallbackObject* asCallbackObject() const { return 0; }
/** Convert 'this' into a UserDataContainer pointer if Object is a UserDataContainer, otherwise return 0.
* Equivalent to dynamic_cast<UserDataContainer*>(this).*/
virtual UserDataContainer* asUserDataContainer() { return 0; }
/** convert 'const this' into a const UserDataContainer pointer if Object is a UserDataContainer, otherwise return 0.
* Equivalent to dynamic_cast<const UserDataContainer*>(this).*/
virtual const UserDataContainer* asUserDataContainer() const { return 0; }
/** Set whether to use a mutex to ensure ref() and unref() are thread safe.*/
virtual void setThreadSafeRefUnref(bool threadSafe);
@ -366,7 +374,6 @@ protected:
};
}
#endif

View File

@ -39,6 +39,14 @@ class OSG_EXPORT UserDataContainer : public osg::Object
by derived classes.*/
virtual const char* className() const { return "UserDataContainer"; }
/** Convert 'this' into a UserDataContainer pointer if Object is a UserDataContainer, otherwise return 0.
* Equivalent to dynamic_cast<UserDataContainer*>(this).*/
virtual UserDataContainer* asUserDataContainer() { return this; }
/** convert 'const this' into a const UserDataContainer pointer if Object is a UserDataContainer, otherwise return 0.
* Equivalent to dynamic_cast<const UserDataContainer*>(this).*/
virtual const UserDataContainer* asUserDataContainer() const { return this; }
/**
* Set user data, data must be subclassed from Referenced to allow
* automatic memory handling. If your own data isn't directly
@ -209,7 +217,6 @@ inline const Object* getUserObject(const osg::Object* object, const std::string&
return udc ? udc->getUserObject(name) : 0;
}
}
#endif

View File

@ -19,6 +19,8 @@
#include <osg/BoundingBox>
#include <osg/BoundingSphere>
#include <typeinfo>
namespace osg {
// forward declare core OSG math classes
@ -126,6 +128,10 @@ class TemplateValueObject : public ValueObject
ValueObject(),
_value() {}
TemplateValueObject(const T& value) :
ValueObject(),
_value(value) {}
TemplateValueObject(const std::string& name, const T& value) :
ValueObject(name),
_value(value) {}
@ -189,12 +195,15 @@ bool osg::Object::getUserValue(const std::string& name, T& value) const
{
typedef TemplateValueObject<T> UserValueObject;
const osg::UserDataContainer* udc = dynamic_cast<const osg::UserDataContainer*>(this);
const osg::UserDataContainer* udc = asUserDataContainer();
if (!udc) udc = _userDataContainer;
const UserValueObject* uvo = udc ? dynamic_cast<const UserValueObject*>(udc->getUserObject(name)) : 0;
if (uvo)
if (!udc) return false;
const Object* obj = udc->getUserObject(name);
if (obj && typeid(*obj)==typeid(UserValueObject))
{
const UserValueObject* uvo = static_cast<const UserValueObject*>(obj);
value = uvo->getValue();
return true;
}
@ -210,7 +219,7 @@ void osg::Object::setUserValue(const std::string& name, const T& value)
{
typedef TemplateValueObject<T> UserValueObject;
osg::UserDataContainer* udc = dynamic_cast<osg::UserDataContainer*>(this);
osg::UserDataContainer* udc = asUserDataContainer();
if (!udc)
{
getOrCreateUserDataContainer();
@ -218,11 +227,62 @@ void osg::Object::setUserValue(const std::string& name, const T& value)
}
unsigned int i = udc->getUserObjectIndex(name);
if (i<udc->getNumUserObjects()) udc->setUserObject(i, new UserValueObject(name,value));
else udc->addUserObject(new UserValueObject(name,value));
if (i<udc->getNumUserObjects())
{
Object* obj = udc->getUserObject(i);
if (typeid(*obj)==typeid(UserValueObject))
{
UserValueObject* uvo = static_cast<UserValueObject*>(obj);
uvo->setValue(value);
}
else
{
udc->setUserObject(i, new UserValueObject(name, value));
}
}
else
{
udc->addUserObject(new UserValueObject(name,value));
}
}
template<class P, class T>
T* getOrCreateUserObjectOfType(P* parent)
{
T* object=0;
const char* name = typeid(T).name();
osg::UserDataContainer* udc = parent->getOrCreateUserDataContainer();
unsigned int index = udc->getUserObjectIndex(name);
if (index<udc->getNumUserObjects())
{
osg::Object* userObject = udc->getUserObject(index);
if (typeid(*userObject)==typeid(T))
{
object = static_cast<T*>(userObject);
// OSG_NOTICE<<"Reusing "<<name<<std::endl;
}
else
{
// OSG_NOTICE<<"Replacing "<<name<<", original object "<<userObject->className()<<std::endl;
object = new T;
object->setName(name);
udc->setUserObject(index, object);
}
}
else
{
object = new T;
object->setName(name);
udc->addUserObject(object);
// OSG_NOTICE<<"Creating new "<<name<<std::endl;
}
return object;
}
}
#endif