diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoAlignableTransform.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoAlignableTransform.h index 009919232450427121dd7dba213bdc1256c77588..3af0c03752dbdce76a62b1778177c19841bb4436 100644 --- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoAlignableTransform.h +++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoAlignableTransform.h @@ -7,6 +7,7 @@ #include "GeoModelKernel/GeoTransform.h" #include <vector> +#include <mutex> class GeoVAlignmentStore; @@ -45,6 +46,10 @@ class GeoAlignableTransform final : public GeoTransform // the memory is unallocated. GeoTrf::Transform3D* m_delta; + // We need to protext m_delta with a mutex in order to avoid + // memory corruption in multithreaded applications + mutable std::mutex m_deltaMutex; + // A list of parents who use this alignable target. They // must all be notified when the alignment changes! std::vector<GeoGraphNode*> m_parentList; diff --git a/GeoModelCore/GeoModelKernel/src/GeoAlignableTransform.cxx b/GeoModelCore/GeoModelKernel/src/GeoAlignableTransform.cxx index 9542340bbe9d10bde31de88b14d769fd8bf9bb0f..b5c0a0e0b1aeb4ef280d29e0c0ec6ec1c01e6161 100755 --- a/GeoModelCore/GeoModelKernel/src/GeoAlignableTransform.cxx +++ b/GeoModelCore/GeoModelKernel/src/GeoAlignableTransform.cxx @@ -29,20 +29,29 @@ __attribute__ ((flatten)) #endif GeoTrf::Transform3D GeoAlignableTransform::getTransform(const GeoVAlignmentStore* store) const { - const GeoTrf::Transform3D* delta = (store==nullptr ? m_delta : store->getDelta(this)); - return GeoTransform::getTransform(nullptr) * (delta==nullptr ? GeoTrf::Transform3D(GeoTrf::Transform3D::Identity()) : *delta); + if(store) { + const GeoTrf::Transform3D* delta = store->getDelta(this); + return GeoTransform::getTransform(nullptr) * (delta==nullptr ? GeoTrf::Transform3D(GeoTrf::Transform3D::Identity()) : *delta); + } + else { + std::scoped_lock<std::mutex> guard(m_deltaMutex); + return GeoTransform::getTransform(nullptr) * (m_delta==nullptr ? GeoTrf::Transform3D(GeoTrf::Transform3D::Identity()) : *m_delta); + } } void GeoAlignableTransform::setDelta (const GeoTrf::Transform3D& delta, GeoVAlignmentStore* store) { if(store==nullptr) { - if(m_delta && (m_delta->isApprox(delta))) return; - - if(m_delta) { - (*m_delta) = delta; - } - else { - m_delta = new GeoTrf::Transform3D(delta); + { + std::scoped_lock<std::mutex> guard(m_deltaMutex); + if(m_delta && (m_delta->isApprox(delta))) return; + + if(m_delta) { + (*m_delta) = delta; + } + else { + m_delta = new GeoTrf::Transform3D(delta); + } } std::set<GeoGraphNode*> uniqueParents; @@ -63,9 +72,11 @@ void GeoAlignableTransform::clearDelta(GeoVAlignmentStore* store) { // Does not make sence to clear deltas inside Alignment Store if(store!=nullptr) return; - - delete m_delta; - m_delta = nullptr; + { + std::scoped_lock<std::mutex> guard(m_deltaMutex); + delete m_delta; + m_delta = nullptr; + } std::set<GeoGraphNode*> uniqueParents; for(GeoGraphNode* parent : m_parentList) {