Class for safely deleting objects that may be active in different threads.
This is now used in the implementation of spin animations.
#include <simgear/structure/SGBinding.hxx>
#include <simgear/scene/material/EffectGeode.hxx>
#include <simgear/scene/material/EffectCullVisitor.hxx>
+#include <simgear/scene/util/DeletionManager.hxx>
#include <simgear/scene/util/OsgMath.hxx>
#include <simgear/scene/util/SGNodeMasks.hxx>
#include <simgear/scene/util/SGSceneUserData.hxx>
// 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)
{
if (!_condition || _condition->test()) {
double t = nv->getFrameStamp()->getReferenceTime();
double rps = _animationValue->getValue() / 60.0;
- ReferenceValues* refval = static_cast<ReferenceValues*>(_referenceValues.get());
- if (!refval || refval->_rotVelocity != rps) {
- ReferenceValues* newref = 0;
- if (!refval) {
+ ref_ptr<ReferenceValues>
+ refval(static_cast<ReferenceValues*>(_referenceValues.get()));
+ if (!refval || refval->_rotVelocity != rps) {
+ ref_ptr<ReferenceValues> 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;
set(HEADERS
CopyOp.hxx
+ DeletionManager.hxx
NodeAndDrawableVisitor.hxx
Noise.hxx
OsgMath.hxx
set(SOURCES
CopyOp.cxx
+ DeletionManager.cxx
NodeAndDrawableVisitor.cxx
Noise.cxx
PrimitiveUtils.cxx
--- /dev/null
+// 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 <OpenThreads/ScopedLock>
+#include <osg/Node>
+#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<OpenThreads::Mutex> lock(_mutex);
+ _staleObjects.resize(0);
+ }
+ return false;
+}
+
+void DeletionManager::addStaleObject(Referenced* obj)
+{
+ OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
+ _staleObjects.push_back(obj);
+}
+
+void DeletionManager::install(Node* node)
+{
+ node->addEventCallback(instance());
+}
+
+DeletionManager* DeletionManager::instance()
+{
+ return SingletonRefPtr<DeletionManager>::instance();
+}
+}
+
--- /dev/null
+// 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 <vector>
+
+#include <OpenThreads/Mutex>
+#include <osg/ref_ptr>
+#include <osg/NodeCallback>
+#include <osg/Referenced>
+#include <osgGA/GUIEventHandler>
+
+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<osg::ref_ptr<osg::Referenced> > _staleObjects;
+};
+}
+
+#endif