From: Tim Moore Date: Fri, 3 Aug 2012 15:15:15 +0000 (+0200) Subject: DeletionManager X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=78a78a17ccfecf58fd9651b0e1de001d86d6d19c;p=simgear.git DeletionManager Class for safely deleting objects that may be active in different threads. This is now used in the implementation of spin animations. --- diff --git a/simgear/scene/model/animation.cxx b/simgear/scene/model/animation.cxx index 25dcb20a..7e94e5e6 100644 --- a/simgear/scene/model/animation.cxx +++ b/simgear/scene/model/animation.cxx @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -778,7 +779,8 @@ protected: // more than one camera. It is probably safe to overwrite the // reference values in multiple threads, but we'll provide a // threadsafe way to manage those values just to be safe. - struct ReferenceValues { + struct ReferenceValues : public osg::Referenced + { ReferenceValues(double t, double rot, double vel) : _time(t), _rotation(rot), _rotVelocity(vel) { @@ -800,19 +802,31 @@ void SpinAnimCallback::operator()(osg::Node* node, osg::NodeVisitor* nv) if (!_condition || _condition->test()) { double t = nv->getFrameStamp()->getReferenceTime(); double rps = _animationValue->getValue() / 60.0; - ReferenceValues* refval = static_cast(_referenceValues.get()); - if (!refval || refval->_rotVelocity != rps) { - ReferenceValues* newref = 0; - if (!refval) { + ref_ptr + refval(static_cast(_referenceValues.get())); + if (!refval || refval->_rotVelocity != rps) { + ref_ptr newref; + if (!refval.valid()) { // initialization newref = new ReferenceValues(t, 0.0, rps); } else { double newRot = refval->_rotation + (t - refval->_time) * refval->_rotVelocity; newref = new ReferenceValues(t, newRot, rps); } + // increment reference pointer, because it will be stored + // naked in _referenceValues. + newref->ref(); if (_referenceValues.assign(newref, refval)) { - delete refval; + if (refval.valid()) { + DeletionManager::instance()->addStaleObject(refval.get()); + refval->unref(); + } + } else { + // Another thread installed new values before us + newref->unref(); } + // Whatever happened, we can use the reference values just + // calculated. refval = newref; } double rotation = refval->_rotation + (t - refval->_time) * rps; diff --git a/simgear/scene/util/CMakeLists.txt b/simgear/scene/util/CMakeLists.txt index 670d21af..4c523c9d 100644 --- a/simgear/scene/util/CMakeLists.txt +++ b/simgear/scene/util/CMakeLists.txt @@ -2,6 +2,7 @@ include (SimGearComponent) set(HEADERS CopyOp.hxx + DeletionManager.hxx NodeAndDrawableVisitor.hxx Noise.hxx OsgMath.hxx @@ -28,6 +29,7 @@ set(HEADERS set(SOURCES CopyOp.cxx + DeletionManager.cxx NodeAndDrawableVisitor.cxx Noise.cxx PrimitiveUtils.cxx diff --git a/simgear/scene/util/DeletionManager.cxx b/simgear/scene/util/DeletionManager.cxx new file mode 100644 index 00000000..dbc24dad --- /dev/null +++ b/simgear/scene/util/DeletionManager.cxx @@ -0,0 +1,58 @@ +// DeletionManager.hxx -- defer deletions to a safe time +// +// Copyright (C) 2012 Tim Moore timoore33@gmail.com +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, +// Boston, MA 02110-1301, USA. + +#include "DeletionManager.hxx" + +#include +#include +#include "OsgSingleton.hxx" + +namespace simgear +{ +using namespace osg; + +bool DeletionManager::handle(const osgGA::GUIEventAdapter& ea, + osgGA::GUIActionAdapter&, + osg::Object*, osg::NodeVisitor*) +{ + if (ea.getEventType() == osgGA::GUIEventAdapter::FRAME) + { + OpenThreads::ScopedLock lock(_mutex); + _staleObjects.resize(0); + } + return false; +} + +void DeletionManager::addStaleObject(Referenced* obj) +{ + OpenThreads::ScopedLock lock(_mutex); + _staleObjects.push_back(obj); +} + +void DeletionManager::install(Node* node) +{ + node->addEventCallback(instance()); +} + +DeletionManager* DeletionManager::instance() +{ + return SingletonRefPtr::instance(); +} +} + diff --git a/simgear/scene/util/DeletionManager.hxx b/simgear/scene/util/DeletionManager.hxx new file mode 100644 index 00000000..82d7410d --- /dev/null +++ b/simgear/scene/util/DeletionManager.hxx @@ -0,0 +1,48 @@ +// DeletionManager.hxx -- defer deletions to a safe time +// +// Copyright (C) 2012 Tim Moore timoore33@gmail.com +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the +// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, +// Boston, MA 02110-1301, USA. + +#ifndef SIMGEAR_DELETIONMANAGER_HXX +#define SIMGEAR_DELETIONMANAGER_HXX 1 + +#include + +#include +#include +#include +#include +#include + +namespace simgear +{ +class DeletionManager : public osgGA::GUIEventHandler +{ +public: + virtual bool handle(const osgGA::GUIEventAdapter& ea, + osgGA::GUIActionAdapter& aa, + osg::Object* object, osg::NodeVisitor* nv); + void addStaleObject(osg::Referenced* obj); + static void install(osg::Node* node); + static DeletionManager* instance(); +protected: + OpenThreads::Mutex _mutex; + std::vector > _staleObjects; +}; +} + +#endif