From 8d2d8650ca62cb927dec81dacdce82e8a47bedc8 Mon Sep 17 00:00:00 2001 From: Pasukhin Dmitry Date: Thu, 2 Apr 2026 17:21:35 +0100 Subject: [PATCH] Foundation, Modeling - Fix thread-safety data races for concurrent operations (#1180) - Refactors `BRepCheck_*` result classes to use an always-present mutex with a parallel-mode guard, and updates the parallel analyzer to use the new locking model. - Makes multiple Foundation-level globals thread-safe via `std::atomic`, adds mutex-based protection for lazy initialization, and introduces `std::call_once` on Windows host initialization. - Converts several TKBool global mutable statics to `thread_local` to prevent cross-thread state corruption. --- .../TKMath/Poly/Poly_Triangulation.cxx | 62 +++++++++------- .../TKMath/Poly/Poly_Triangulation.hxx | 8 ++- .../TKernel/OSD/OSD_Host.cxx | 32 ++++----- .../TKernel/OSD/OSD_Parallel.cxx | 9 ++- .../TKernel/OSD/OSD_signal.cxx | 12 ++-- .../TKernel/Plugin/Plugin.cxx | 34 ++++++--- .../TKernel/Resource/Resource_Unicode.cxx | 70 ++++++++++--------- .../TKernel/Standard/Standard_Failure.cxx | 3 +- src/FoundationClasses/TKernel/Units/Units.cxx | 24 +++++-- .../TKernel/UnitsAPI/UnitsAPI.cxx | 57 ++++++++++----- .../TKernel/UnitsMethods/UnitsMethods.cxx | 4 +- .../TKBool/TopOpeBRep/TopOpeBRep_vprdeg.cxx | 8 ++- .../TopOpeBRepBuild_HBuilder.cxx | 4 +- .../TopOpeBRepBuild/TopOpeBRepBuild_ffsfs.cxx | 4 +- .../TopOpeBRepDS_CurveExplorer.cxx | 2 +- .../TopOpeBRepDS_FaceInterferenceTool.cxx | 2 +- .../TopOpeBRepDS/TopOpeBRepDS_connex.cxx | 23 +++--- .../TopOpeBRepTool/TopOpeBRepTool_2d.cxx | 21 +++--- .../TopOpeBRepTool/TopOpeBRepTool_SC.cxx | 2 +- .../BRepCheck/BRepCheck_Analyzer.cxx | 17 +++-- .../TKTopAlgo/BRepCheck/BRepCheck_Edge.cxx | 16 +++-- .../TKTopAlgo/BRepCheck/BRepCheck_Face.cxx | 42 +++++++---- .../TKTopAlgo/BRepCheck/BRepCheck_Result.cxx | 17 ++--- .../TKTopAlgo/BRepCheck/BRepCheck_Result.hxx | 16 ++--- .../TKTopAlgo/BRepCheck/BRepCheck_Shell.cxx | 35 +++++++--- .../TKTopAlgo/BRepCheck/BRepCheck_Vertex.cxx | 7 +- .../TKTopAlgo/BRepCheck/BRepCheck_Wire.cxx | 35 +++++++--- 27 files changed, 360 insertions(+), 206 deletions(-) diff --git a/src/FoundationClasses/TKMath/Poly/Poly_Triangulation.cxx b/src/FoundationClasses/TKMath/Poly/Poly_Triangulation.cxx index f6f330b384..a21afe9514 100644 --- a/src/FoundationClasses/TKMath/Poly/Poly_Triangulation.cxx +++ b/src/FoundationClasses/TKMath/Poly/Poly_Triangulation.cxx @@ -22,13 +22,14 @@ #include #include +#include + IMPLEMENT_STANDARD_RTTIEXT(Poly_Triangulation, Standard_Transient) //================================================================================================= Poly_Triangulation::Poly_Triangulation() - : myCachedMinMax(nullptr), - myDeflection(0), + : myDeflection(0), myPurpose(Poly_MeshPurpose_NONE) { } @@ -39,8 +40,7 @@ Poly_Triangulation::Poly_Triangulation(const int theNbNodes, const int theNbTriangles, const bool theHasUVNodes, const bool theHasNormals) - : myCachedMinMax(nullptr), - myDeflection(0), + : myDeflection(0), myNodes(theNbNodes), myTriangles(1, theNbTriangles), myPurpose(Poly_MeshPurpose_NONE) @@ -59,8 +59,7 @@ Poly_Triangulation::Poly_Triangulation(const int theNbNodes, Poly_Triangulation::Poly_Triangulation(const NCollection_Array1& theNodes, const NCollection_Array1& theTriangles) - : myCachedMinMax(nullptr), - myDeflection(0), + : myDeflection(0), myNodes(theNodes.Length()), myTriangles(1, theTriangles.Length()), myPurpose(Poly_MeshPurpose_NONE) @@ -75,8 +74,7 @@ Poly_Triangulation::Poly_Triangulation(const NCollection_Array1& Poly_Triangulation::Poly_Triangulation(const NCollection_Array1& theNodes, const NCollection_Array1& theUVNodes, const NCollection_Array1& theTriangles) - : myCachedMinMax(nullptr), - myDeflection(0), + : myDeflection(0), myNodes(theNodes.Length()), myTriangles(1, theTriangles.Length()), myUVNodes(theNodes.Length()), @@ -93,7 +91,7 @@ Poly_Triangulation::Poly_Triangulation(const NCollection_Array1& Poly_Triangulation::~Poly_Triangulation() { - delete myCachedMinMax; + delete myCachedMinMax.load(std::memory_order_acquire); } //================================================================================================= @@ -106,8 +104,7 @@ occ::handle Poly_Triangulation::Copy() const //================================================================================================= Poly_Triangulation::Poly_Triangulation(const occ::handle& theTriangulation) - : myCachedMinMax(nullptr), - myDeflection(theTriangulation->myDeflection), + : myDeflection(theTriangulation->myDeflection), myNodes(theTriangulation->myNodes), myTriangles(theTriangulation->myTriangles), myUVNodes(theTriangulation->myUVNodes), @@ -341,8 +338,10 @@ void Poly_Triangulation::DumpJson(Standard_OStream& theOStream, int) const const Bnd_Box& Poly_Triangulation::CachedMinMax() const { - static const Bnd_Box anEmptyBox; - return (myCachedMinMax == nullptr) ? anEmptyBox : *myCachedMinMax; + static const Bnd_Box anEmptyBox; + std::shared_lock aLock(myCachedMinMaxMutex); + const Bnd_Box* aBox = myCachedMinMax.load(std::memory_order_relaxed); + return (aBox == nullptr) ? anEmptyBox : *aBox; } //================================================================================================= @@ -354,19 +353,28 @@ void Poly_Triangulation::SetCachedMinMax(const Bnd_Box& theBox) unsetCachedMinMax(); return; } - if (myCachedMinMax == nullptr) + std::unique_lock aLock(myCachedMinMaxMutex); + Bnd_Box* aBox = myCachedMinMax.load(std::memory_order_relaxed); + if (aBox == nullptr) { - myCachedMinMax = new Bnd_Box(); + aBox = new Bnd_Box(); + *aBox = theBox; + myCachedMinMax.store(aBox, std::memory_order_release); + } + else + { + *aBox = theBox; } - *myCachedMinMax = theBox; } //================================================================================================= void Poly_Triangulation::unsetCachedMinMax() { - delete myCachedMinMax; - myCachedMinMax = nullptr; + std::unique_lock aLock(myCachedMinMaxMutex); + Bnd_Box* aBox = myCachedMinMax.load(std::memory_order_relaxed); + myCachedMinMax.store(nullptr, std::memory_order_release); + delete aBox; } //================================================================================================= @@ -376,14 +384,20 @@ bool Poly_Triangulation::MinMax(Bnd_Box& theBox, const bool theIsAccurate) const { Bnd_Box aBox; - if (HasCachedMinMax() - && (!HasGeometry() || !theIsAccurate || theTrsf.Form() == gp_Identity - || theTrsf.Form() == gp_Translation || theTrsf.Form() == gp_PntMirror - || theTrsf.Form() == gp_Scale)) + bool aUsedCache = false; { - aBox = myCachedMinMax->Transformed(theTrsf); + std::shared_lock aLock(myCachedMinMaxMutex); + const Bnd_Box* aCachedBox = myCachedMinMax.load(std::memory_order_relaxed); + if (aCachedBox != nullptr + && (!HasGeometry() || !theIsAccurate || theTrsf.Form() == gp_Identity + || theTrsf.Form() == gp_Translation || theTrsf.Form() == gp_PntMirror + || theTrsf.Form() == gp_Scale)) + { + aBox = aCachedBox->Transformed(theTrsf); + aUsedCache = true; + } } - else + if (!aUsedCache) { aBox = computeBoundingBox(theTrsf); } diff --git a/src/FoundationClasses/TKMath/Poly/Poly_Triangulation.hxx b/src/FoundationClasses/TKMath/Poly/Poly_Triangulation.hxx index c6bcc14f2b..02f36ed5a0 100644 --- a/src/FoundationClasses/TKMath/Poly/Poly_Triangulation.hxx +++ b/src/FoundationClasses/TKMath/Poly/Poly_Triangulation.hxx @@ -28,6 +28,9 @@ #include #include +#include +#include + class OSD_FileSystem; class Poly_Triangulation; class Poly_TriangulationParameters; @@ -222,7 +225,7 @@ public: Standard_EXPORT void SetCachedMinMax(const Bnd_Box& theBox); //! Returns TRUE if there is some cached min - max range of this triangulation. - Standard_EXPORT bool HasCachedMinMax() const { return myCachedMinMax != nullptr; } + bool HasCachedMinMax() const { return myCachedMinMax.load(std::memory_order_acquire) != nullptr; } //! Updates cached min - max range of this triangulation with bounding box of nodal data. void UpdateCachedMinMax() @@ -386,7 +389,8 @@ protected: Standard_EXPORT virtual Bnd_Box computeBoundingBox(const gp_Trsf& theTrsf) const; protected: - Bnd_Box* myCachedMinMax; + mutable std::atomic myCachedMinMax{nullptr}; + mutable std::shared_mutex myCachedMinMaxMutex; double myDeflection; Poly_ArrayOfNodes myNodes; NCollection_Array1 myTriangles; diff --git a/src/FoundationClasses/TKernel/OSD/OSD_Host.cxx b/src/FoundationClasses/TKernel/OSD/OSD_Host.cxx index 7cfe893581..f12ac14e2f 100644 --- a/src/FoundationClasses/TKernel/OSD/OSD_Host.cxx +++ b/src/FoundationClasses/TKernel/OSD/OSD_Host.cxx @@ -219,30 +219,31 @@ int OSD_Host::Error() const #include + #include + void _osd_wnt_set_error(OSD_Error&, int, ...); -static BOOL fInit = FALSE; static TCollection_AsciiString hostName; static TCollection_AsciiString version; static TCollection_AsciiString interAddr; static int memSize; +static std::once_flag THE_HOST_INIT_FLAG; OSD_Host ::OSD_Host() { #ifndef OCCT_UWP - DWORD nSize; - char szHostName[MAX_COMPUTERNAME_LENGTH + 1]; - char* hostAddr = 0; - MEMORYSTATUS ms; - WSADATA wd; - PHOSTENT phe; - IN_ADDR inAddr; - OSVERSIONINFOW osVerInfo; + static bool THE_HOST_INIT_SUCCESS = false; - if (!fInit) - { + std::call_once(THE_HOST_INIT_FLAG, [&]() { + DWORD nSize = MAX_COMPUTERNAME_LENGTH + 1; + char szHostName[MAX_COMPUTERNAME_LENGTH + 1]; + char* hostAddr = 0; + MEMORYSTATUS ms; + WSADATA wd; + PHOSTENT phe; + IN_ADDR inAddr; + OSVERSIONINFOW osVerInfo; - nSize = MAX_COMPUTERNAME_LENGTH + 1; ZeroMemory(&osVerInfo, sizeof(OSVERSIONINFOW)); osVerInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); @@ -304,13 +305,12 @@ OSD_Host ::OSD_Host() } version = aVersion; - fInit = TRUE; + THE_HOST_INIT_SUCCESS = true; } // end if + }); // end call_once - } // end if - - if (fInit) + if (THE_HOST_INIT_SUCCESS) myName = hostName; #endif diff --git a/src/FoundationClasses/TKernel/OSD/OSD_Parallel.cxx b/src/FoundationClasses/TKernel/OSD/OSD_Parallel.cxx index cc96a07323..1f7b98a2d4 100644 --- a/src/FoundationClasses/TKernel/OSD/OSD_Parallel.cxx +++ b/src/FoundationClasses/TKernel/OSD/OSD_Parallel.cxx @@ -16,6 +16,8 @@ #include +#include + #ifdef _WIN32 #include #include @@ -173,12 +175,13 @@ static uint32_t readCpuMask(const char* thePath) } #endif -static bool OSD_Parallel_ToUseOcctThreads = +static std::atomic OSD_Parallel_ToUseOcctThreads{ #ifdef HAVE_TBB - false; + false #else - true; + true #endif +}; } // namespace //================================================================================================= diff --git a/src/FoundationClasses/TKernel/OSD/OSD_signal.cxx b/src/FoundationClasses/TKernel/OSD/OSD_signal.cxx index 05c1c2faf4..11b7077691 100644 --- a/src/FoundationClasses/TKernel/OSD/OSD_signal.cxx +++ b/src/FoundationClasses/TKernel/OSD/OSD_signal.cxx @@ -19,13 +19,14 @@ #include #include +#include #include #include #include -static OSD_SignalMode OSD_WasSetSignal = OSD_SignalMode_AsIs; -static int OSD_SignalStackTraceLength = 0; +static std::atomic OSD_WasSetSignal{OSD_SignalMode_AsIs}; +static std::atomic OSD_SignalStackTraceLength{0}; //================================================================================================= @@ -753,7 +754,7 @@ static bool fCtrlBrk; // const OSD_WhoAmI Iam = OSD_WPackage; typedef void(ACT_SIGIO_HANDLER)(); -ACT_SIGIO_HANDLER* ADR_ACT_SIGIO_HANDLER = nullptr; +std::atomic ADR_ACT_SIGIO_HANDLER{nullptr}; #ifdef __GNUC__ #include @@ -810,8 +811,9 @@ static void Handler(const int theSignal) // std::cout << "OSD::Handler: signal " << (int) theSignal << " occurred inside a try block " << // std::endl ; - if (ADR_ACT_SIGIO_HANDLER != nullptr) - (*ADR_ACT_SIGIO_HANDLER)(); + ACT_SIGIO_HANDLER* aSigHandler = ADR_ACT_SIGIO_HANDLER.load(std::memory_order_acquire); + if (aSigHandler != nullptr) + (*aSigHandler)(); sigset_t set; sigemptyset(&set); diff --git a/src/FoundationClasses/TKernel/Plugin/Plugin.cxx b/src/FoundationClasses/TKernel/Plugin/Plugin.cxx index 424eeb5e8f..f1967dd20c 100644 --- a/src/FoundationClasses/TKernel/Plugin/Plugin.cxx +++ b/src/FoundationClasses/TKernel/Plugin/Plugin.cxx @@ -26,24 +26,40 @@ #include -static char tc[1000]; -static Standard_PCharacter thePluginId = tc; +#include +#include //================================================================================================= occ::handle Plugin::Load(const Standard_GUID& aGUID, const bool theVerbose) { + char aPluginIdBuf[1000]; + Standard_PCharacter aPluginId = aPluginIdBuf; + aGUID.ToCString(aPluginId); + TCollection_AsciiString pid(aPluginId); - aGUID.ToCString(thePluginId); - TCollection_AsciiString pid(thePluginId); + static std::shared_mutex aMapMutex; static NCollection_DataMap theMapOfFunctions; OSD_Function f; + // Fast path: read-only cache lookup under shared lock. + { + std::shared_lock aReadLock(aMapMutex); + if (theMapOfFunctions.Find(pid, f)) + { + aReadLock.unlock(); + Standard_Transient* (*fp)(const Standard_GUID&) = + reinterpret_cast(reinterpret_cast(f)); + return (*fp)(aGUID); + } + } + + // Slow path: exclusive lock for plugin loading. + std::unique_lock aWriteLock(aMapMutex); if (!theMapOfFunctions.IsBound(pid)) { - occ::handle PluginResource = new Resource_Manager("Plugin"); - TCollection_AsciiString theResource(thePluginId); + TCollection_AsciiString theResource(aPluginId); theResource += ".Location"; if (!PluginResource->Find(theResource.ToCString())) @@ -97,12 +113,14 @@ occ::handle Plugin::Load(const Standard_GUID& aGUID, const b theMapOfFunctions.Bind(pid, f); } else + { f = theMapOfFunctions(pid); + } + aWriteLock.unlock(); // Cast through void* to avoid -Wcast-function-type-mismatch warning. // This is safe for dynamically loaded plugin symbols. Standard_Transient* (*fp)(const Standard_GUID&) = reinterpret_cast(reinterpret_cast(f)); - occ::handle theServiceFactory = (*fp)(aGUID); - return theServiceFactory; + return (*fp)(aGUID); } diff --git a/src/FoundationClasses/TKernel/Resource/Resource_Unicode.cxx b/src/FoundationClasses/TKernel/Resource/Resource_Unicode.cxx index e4e93d6a16..45c112a60f 100644 --- a/src/FoundationClasses/TKernel/Resource/Resource_Unicode.cxx +++ b/src/FoundationClasses/TKernel/Resource/Resource_Unicode.cxx @@ -21,6 +21,9 @@ #include #include #include + +#include +#include #include "Resource_CodePages.pxx" #include "Resource_GBK.pxx" #include "Resource_Big5.pxx" @@ -583,58 +586,61 @@ bool Resource_Unicode::ConvertUnicodeToANSI(const TCollection_ExtendedString& fr return true; } -static bool AlreadyRead = false; +static std::atomic AlreadyRead{false}; +static std::atomic TheFormat{Resource_ANSI}; +static std::mutex TheFormatMutex; -static Resource_FormatType& Resource_Current_Format() +static void readFormatFromConfig() { - static Resource_FormatType theformat = Resource_ANSI; - if (!AlreadyRead) + Resource_FormatType aFormat = Resource_ANSI; + occ::handle mgr = new Resource_Manager("CharSet"); + if (mgr->Find("FormatType")) { - AlreadyRead = true; - occ::handle mgr = new Resource_Manager("CharSet"); - if (mgr->Find("FormatType")) + TCollection_AsciiString form = mgr->Value("FormatType"); + if (form.IsEqual("SJIS")) { - TCollection_AsciiString form = mgr->Value("FormatType"); - if (form.IsEqual("SJIS")) - { - theformat = Resource_SJIS; - } - else if (form.IsEqual("EUC")) - { - theformat = Resource_EUC; - } - else if (form.IsEqual("GB")) - { - theformat = Resource_GB; - } - else - { - theformat = Resource_ANSI; - } + aFormat = Resource_SJIS; } - else + else if (form.IsEqual("EUC")) { - theformat = Resource_ANSI; + aFormat = Resource_EUC; + } + else if (form.IsEqual("GB")) + { + aFormat = Resource_GB; } } - return theformat; + TheFormat.store(aFormat, std::memory_order_relaxed); } void Resource_Unicode::SetFormat(const Resource_FormatType typecode) { - AlreadyRead = true; - Resource_Current_Format() = typecode; + std::lock_guard aLock(TheFormatMutex); + TheFormat.store(typecode, std::memory_order_relaxed); + AlreadyRead.store(true, std::memory_order_release); } Resource_FormatType Resource_Unicode::GetFormat() { - return Resource_Current_Format(); + if (AlreadyRead.load(std::memory_order_acquire)) + { + return TheFormat.load(std::memory_order_relaxed); + } + std::lock_guard aLock(TheFormatMutex); + if (!AlreadyRead.load(std::memory_order_relaxed)) + { + readFormatFromConfig(); + AlreadyRead.store(true, std::memory_order_release); + } + return TheFormat.load(std::memory_order_relaxed); } void Resource_Unicode::ReadFormat() { - AlreadyRead = false; - Resource_Unicode::GetFormat(); + std::lock_guard aLock(TheFormatMutex); + AlreadyRead.store(false, std::memory_order_relaxed); + readFormatFromConfig(); + AlreadyRead.store(true, std::memory_order_release); } void Resource_Unicode::ConvertFormatToUnicode(const Resource_FormatType theFormat, diff --git a/src/FoundationClasses/TKernel/Standard/Standard_Failure.cxx b/src/FoundationClasses/TKernel/Standard/Standard_Failure.cxx index dc1e61da76..cf85853f99 100644 --- a/src/FoundationClasses/TKernel/Standard/Standard_Failure.cxx +++ b/src/FoundationClasses/TKernel/Standard/Standard_Failure.cxx @@ -17,12 +17,13 @@ #include #include +#include #include namespace { //! Global parameter defining default length of stack trace. -static int Standard_Failure_DefaultStackTraceLength = 0; +static std::atomic Standard_Failure_DefaultStackTraceLength{0}; } // namespace //================================================================================================= diff --git a/src/FoundationClasses/TKernel/Units/Units.cxx b/src/FoundationClasses/TKernel/Units/Units.cxx index 62199ee6bd..01d6a65473 100644 --- a/src/FoundationClasses/TKernel/Units/Units.cxx +++ b/src/FoundationClasses/TKernel/Units/Units.cxx @@ -33,6 +33,7 @@ #include #include +#include static occ::handle nulldimensions; static occ::handle lexiconunits; @@ -46,10 +47,13 @@ static TCollection_AsciiString lastunit; static occ::handle lastdimension; static double lastvalue, lastmove; +static std::recursive_mutex THE_UNITS_MUTEX; + //================================================================================================= void Units::UnitsFile(const char* const afile) { + std::lock_guard aLock(THE_UNITS_MUTEX); unitsfile = TCollection_AsciiString(afile); } @@ -57,6 +61,7 @@ void Units::UnitsFile(const char* const afile) void Units::LexiconFile(const char* const afile) { + std::lock_guard aLock(THE_UNITS_MUTEX); lexiconfile = TCollection_AsciiString(afile); } @@ -64,6 +69,7 @@ void Units::LexiconFile(const char* const afile) occ::handle Units::DictionaryOfUnits(const bool amode) { + std::lock_guard aLock(THE_UNITS_MUTEX); if (unitsdictionary.IsNull()) { // std::cout<<"Allocation du dictionnaire"< Units::DictionaryOfUnits(const bool amode) occ::handle Units::Quantity(const char* const aquantity) { + std::lock_guard aLock(THE_UNITS_MUTEX); int index; occ::handle quantity; occ::handle nullquantity; @@ -109,6 +116,7 @@ static TCollection_AsciiString symbol_string, quantity_string; const char* Units::FirstQuantity(const char* const aunit) { + std::lock_guard aLock(THE_UNITS_MUTEX); int i, j, k; occ::handle thequantity; occ::handle>> quantitiessequence; @@ -151,6 +159,7 @@ const char* Units::FirstQuantity(const char* const aunit) occ::handle Units::LexiconUnits(const bool amode) { + std::lock_guard aLock(THE_UNITS_MUTEX); if (lexiconunits.IsNull()) { // std::cout<<"Allocation du lexique d'unites"< Units::LexiconUnits(const bool amode) occ::handle Units::LexiconFormula() { + std::lock_guard aLock(THE_UNITS_MUTEX); if (lexiconformula.IsNull()) { // std::cout<<"Allocation du lexique d'expression"< Units::LexiconFormula() occ::handle Units::NullDimensions() { + std::lock_guard aLock(THE_UNITS_MUTEX); if (nulldimensions.IsNull()) nulldimensions = new Units_Dimensions(0., 0., 0., 0., 0., 0., 0., 0., 0.); return nulldimensions; @@ -190,7 +201,8 @@ double Units::Convert(const double avalue, const char* const afirstunit, const char* const asecondunit) { - Units_Measurement measurement(avalue, afirstunit); + std::lock_guard aLock(THE_UNITS_MUTEX); + Units_Measurement measurement(avalue, afirstunit); measurement.Convert(asecondunit); return measurement.Measurement(); } @@ -199,8 +211,8 @@ double Units::Convert(const double avalue, double Units::ToSI(const double aData, const char* const aUnit) { - - occ::handle aDimBid; + std::lock_guard aLock(THE_UNITS_MUTEX); + occ::handle aDimBid; return Units::ToSI(aData, aUnit, aDimBid); } @@ -208,6 +220,7 @@ double Units::ToSI(const double aData, const char* const aUnit) double Units::ToSI(const double aData, const char* const aUnit, occ::handle& dim) { + std::lock_guard aLock(THE_UNITS_MUTEX); if (lastunit != aUnit) { Units_UnitSentence unitsentence(aUnit); @@ -237,7 +250,8 @@ double Units::ToSI(const double aData, const char* const aUnit, occ::handle aDimBid; + std::lock_guard aLock(THE_UNITS_MUTEX); + occ::handle aDimBid; return Units::FromSI(aData, aUnit, aDimBid); } @@ -247,6 +261,7 @@ double Units::FromSI(const double aData, const char* const aUnit, occ::handle& dim) { + std::lock_guard aLock(THE_UNITS_MUTEX); if (lastunit != aUnit) { Units_UnitSentence unitsentence(aUnit); @@ -276,6 +291,7 @@ double Units::FromSI(const double aData, occ::handle Units::Dimensions(const char* const aType) { + std::lock_guard aLock(THE_UNITS_MUTEX); if (aType) { occ::handle dico = Units::DictionaryOfUnits(false); diff --git a/src/FoundationClasses/TKernel/UnitsAPI/UnitsAPI.cxx b/src/FoundationClasses/TKernel/UnitsAPI/UnitsAPI.cxx index 9b06b6e50d..941c9f68c3 100644 --- a/src/FoundationClasses/TKernel/UnitsAPI/UnitsAPI.cxx +++ b/src/FoundationClasses/TKernel/UnitsAPI/UnitsAPI.cxx @@ -19,11 +19,14 @@ #include #include +#include + static occ::handle CurrentUnits, SICurrentUnits, MDTVCurrentUnits; static Units_UnitsSystem LocalSystemUnits, SILocalSystemUnits, MDTVLocalSystemUnits; static TCollection_AsciiString rstring; static UnitsAPI_SystemUnits localSystem = UnitsAPI_SI; static UnitsAPI_SystemUnits currentSystem = UnitsAPI_DEFAULT; +static std::recursive_mutex THE_UNITS_API_MUTEX; //================================================================================================= @@ -135,7 +138,8 @@ void UnitsAPI::CheckLoading(const UnitsAPI_SystemUnits aSystemUnits) double UnitsAPI::CurrentToLS(const double aData, const char* const aQuantity) { - double aValue = aData; + std::lock_guard aLock(THE_UNITS_API_MUTEX); + double aValue = aData; CheckLoading(localSystem); if (CurrentUnits->Find(aQuantity)) { @@ -158,7 +162,8 @@ double UnitsAPI::CurrentToLS(const double aData, const char* const aQuantity) double UnitsAPI::CurrentToSI(const double aData, const char* const aQuantity) { - double aValue = aData; + std::lock_guard aLock(THE_UNITS_API_MUTEX); + double aValue = aData; CheckLoading(UnitsAPI_DEFAULT); if (CurrentUnits->Find(aQuantity)) { @@ -180,7 +185,8 @@ double UnitsAPI::CurrentToSI(const double aData, const char* const aQuantity) double UnitsAPI::CurrentFromLS(const double aData, const char* const aQuantity) { - double aValue = aData; + std::lock_guard aLock(THE_UNITS_API_MUTEX); + double aValue = aData; CheckLoading(localSystem); if (CurrentUnits->Find(aQuantity)) { @@ -203,7 +209,8 @@ double UnitsAPI::CurrentFromLS(const double aData, const char* const aQuantity) double UnitsAPI::CurrentFromSI(const double aData, const char* const aQuantity) { - double aValue = aData; + std::lock_guard aLock(THE_UNITS_API_MUTEX); + double aValue = aData; CheckLoading(UnitsAPI_DEFAULT); if (CurrentUnits->Find(aQuantity)) { @@ -227,7 +234,8 @@ double UnitsAPI::CurrentToAny(const double aData, const char* const aQuantity, const char* const aUnit) { - double aValue = aData; + std::lock_guard aLock(THE_UNITS_API_MUTEX); + double aValue = aData; CheckLoading(UnitsAPI_DEFAULT); if (CurrentUnits->Find(aQuantity)) { @@ -251,7 +259,8 @@ double UnitsAPI::CurrentFromAny(const double aData, const char* const aQuantity, const char* const aUnit) { - double aValue = aData; + std::lock_guard aLock(THE_UNITS_API_MUTEX); + double aValue = aData; CheckLoading(UnitsAPI_DEFAULT); if (CurrentUnits->Find(aQuantity)) { @@ -273,7 +282,8 @@ double UnitsAPI::CurrentFromAny(const double aData, double UnitsAPI::AnyToLS(const double aData, const char* const aUnit) { - double aValue = aData; + std::lock_guard aLock(THE_UNITS_API_MUTEX); + double aValue = aData; CheckLoading(localSystem); occ::handle aDim; aValue = Units::ToSI(aValue, aUnit, aDim); @@ -298,7 +308,8 @@ double UnitsAPI::AnyToLS(const double aData, const char* const aUnit, occ::handle& aDim) { - double aValue = aData; + std::lock_guard aLock(THE_UNITS_API_MUTEX); + double aValue = aData; CheckLoading(localSystem); aValue = Units::ToSI(aValue, aUnit, aDim); const char* quantity = aDim->Quantity(); @@ -320,7 +331,8 @@ double UnitsAPI::AnyToLS(const double aData, double UnitsAPI::AnyToSI(const double aData, const char* const aUnit) { - double aValue; + std::lock_guard aLock(THE_UNITS_API_MUTEX); + double aValue; CheckLoading(UnitsAPI_DEFAULT); aValue = Units::ToSI(aData, aUnit); return aValue; @@ -332,7 +344,8 @@ double UnitsAPI::AnyToSI(const double aData, const char* const aUnit, occ::handle& aDim) { - double aValue; + std::lock_guard aLock(THE_UNITS_API_MUTEX); + double aValue; CheckLoading(UnitsAPI_DEFAULT); aValue = Units::ToSI(aData, aUnit, aDim); return aValue; @@ -342,7 +355,8 @@ double UnitsAPI::AnyToSI(const double aData, double UnitsAPI::AnyFromLS(const double aData, const char* const aUnit) { - double aValue = aData; + std::lock_guard aLock(THE_UNITS_API_MUTEX); + double aValue = aData; CheckLoading(localSystem); occ::handle aDim; aValue = Units::FromSI(aValue, aUnit, aDim); @@ -364,7 +378,8 @@ double UnitsAPI::AnyFromLS(const double aData, const char* const aUnit) double UnitsAPI::AnyFromSI(const double aData, const char* const aUnit) { - double aValue; + std::lock_guard aLock(THE_UNITS_API_MUTEX); + double aValue; CheckLoading(UnitsAPI_DEFAULT); aValue = Units::FromSI(aData, aUnit); return aValue; @@ -374,7 +389,8 @@ double UnitsAPI::AnyFromSI(const double aData, const char* const aUnit) double UnitsAPI::AnyToAny(const double aData, const char* const aUnit1, const char* const aUnit2) { - double aValue = aData; + std::lock_guard aLock(THE_UNITS_API_MUTEX); + double aValue = aData; CheckLoading(UnitsAPI_DEFAULT); aValue = Units::Convert(aValue, aUnit1, aUnit2); return aValue; @@ -384,7 +400,8 @@ double UnitsAPI::AnyToAny(const double aData, const char* const aUnit1, const ch double UnitsAPI::LSToSI(const double aData, const char* const aQuantity) { - double aValue = aData; + std::lock_guard aLock(THE_UNITS_API_MUTEX); + double aValue = aData; CheckLoading(localSystem); if (CurrentUnits->Find(aQuantity)) { @@ -405,7 +422,8 @@ double UnitsAPI::LSToSI(const double aData, const char* const aQuantity) double UnitsAPI::SIToLS(const double aData, const char* const aQuantity) { - double aValue = aData; + std::lock_guard aLock(THE_UNITS_API_MUTEX); + double aValue = aData; CheckLoading(localSystem); if (CurrentUnits->Find(aQuantity)) { @@ -426,6 +444,7 @@ double UnitsAPI::SIToLS(const double aData, const char* const aQuantity) void UnitsAPI::SetLocalSystem(const UnitsAPI_SystemUnits aSystemUnits) { + std::lock_guard aLock(THE_UNITS_API_MUTEX); CheckLoading(aSystemUnits); localSystem = currentSystem; } @@ -434,6 +453,7 @@ void UnitsAPI::SetLocalSystem(const UnitsAPI_SystemUnits aSystemUnits) UnitsAPI_SystemUnits UnitsAPI::LocalSystem() { + std::lock_guard aLock(THE_UNITS_API_MUTEX); return localSystem; } @@ -441,6 +461,7 @@ UnitsAPI_SystemUnits UnitsAPI::LocalSystem() void UnitsAPI::SetCurrentUnit(const char* const aQuantity, const char* const anUnit) { + std::lock_guard aLock(THE_UNITS_API_MUTEX); CheckLoading(localSystem); CurrentUnits->SetResource(aQuantity, anUnit); } @@ -449,6 +470,7 @@ void UnitsAPI::SetCurrentUnit(const char* const aQuantity, const char* const anU void UnitsAPI::Save() { + std::lock_guard aLock(THE_UNITS_API_MUTEX); CheckLoading(localSystem); CurrentUnits->Save(); } @@ -457,6 +479,7 @@ void UnitsAPI::Save() void UnitsAPI::Reload() { + std::lock_guard aLock(THE_UNITS_API_MUTEX); currentSystem = UnitsAPI_DEFAULT; CheckLoading(localSystem); } @@ -467,6 +490,7 @@ static TCollection_AsciiString astring; const char* UnitsAPI::CurrentUnit(const char* const aQuantity) { + std::lock_guard aLock(THE_UNITS_API_MUTEX); CheckLoading(localSystem); astring = CurrentUnits->Value(aQuantity); return astring.ToCString(); @@ -553,7 +577,8 @@ occ::handle UnitsAPI::DimensionSolidAngle() bool UnitsAPI::Check(const char* const aQuantity, const char* const /*aUnit*/) { - bool status = false; + std::lock_guard aLock(THE_UNITS_API_MUTEX); + bool status = false; CheckLoading(UnitsAPI_DEFAULT); if (CurrentUnits->Find(aQuantity)) { diff --git a/src/FoundationClasses/TKernel/UnitsMethods/UnitsMethods.cxx b/src/FoundationClasses/TKernel/UnitsMethods/UnitsMethods.cxx index 4c19eedadb..afeaf2dc9f 100644 --- a/src/FoundationClasses/TKernel/UnitsMethods/UnitsMethods.cxx +++ b/src/FoundationClasses/TKernel/UnitsMethods/UnitsMethods.cxx @@ -15,7 +15,9 @@ #include -static double UnitsMethods_CascadeLengthUnit = 1.; +#include + +static std::atomic UnitsMethods_CascadeLengthUnit{1.}; //================================================================================================= diff --git a/src/ModelingAlgorithms/TKBool/TopOpeBRep/TopOpeBRep_vprdeg.cxx b/src/ModelingAlgorithms/TKBool/TopOpeBRep/TopOpeBRep_vprdeg.cxx index d02cf5b5da..59418d19c0 100644 --- a/src/ModelingAlgorithms/TKBool/TopOpeBRep/TopOpeBRep_vprdeg.cxx +++ b/src/ModelingAlgorithms/TKBool/TopOpeBRep/TopOpeBRep_vprdeg.cxx @@ -44,9 +44,11 @@ #define M_REVERSED(st) (st == TopAbs_REVERSED) // modified by NIZHNY-MKK Tue Nov 21 17:30:23 2000.BEGIN -static NCollection_DataMap, TopTools_ShapeMapHasher> - aMapOfTreatedVertexListOfEdge; -static TopOpeBRep_PLineInter localCurrentLine = nullptr; +static thread_local NCollection_DataMap, + TopTools_ShapeMapHasher> + aMapOfTreatedVertexListOfEdge; +static thread_local TopOpeBRep_PLineInter localCurrentLine = nullptr; static bool local_FindTreatedEdgeOnVertex(const TopoDS_Edge& theEdge, const TopoDS_Vertex& theVertex); diff --git a/src/ModelingAlgorithms/TKBool/TopOpeBRepBuild/TopOpeBRepBuild_HBuilder.cxx b/src/ModelingAlgorithms/TKBool/TopOpeBRepBuild/TopOpeBRepBuild_HBuilder.cxx index c9a28a25fb..2af142e9ad 100644 --- a/src/ModelingAlgorithms/TKBool/TopOpeBRepBuild/TopOpeBRepBuild_HBuilder.cxx +++ b/src/ModelingAlgorithms/TKBool/TopOpeBRepBuild/TopOpeBRepBuild_HBuilder.cxx @@ -194,8 +194,8 @@ const NCollection_List& TopOpeBRepBuild_HBuilder::Section() return L; } -static NCollection_List* PLE = nullptr; -static NCollection_List::Iterator* PITLE = nullptr; +static thread_local NCollection_List* PLE = nullptr; +static thread_local NCollection_List::Iterator* PITLE = nullptr; //================================================================================================= diff --git a/src/ModelingAlgorithms/TKBool/TopOpeBRepBuild/TopOpeBRepBuild_ffsfs.cxx b/src/ModelingAlgorithms/TKBool/TopOpeBRepBuild/TopOpeBRepBuild_ffsfs.cxx index ead15b4465..ed7b646821 100644 --- a/src/ModelingAlgorithms/TKBool/TopOpeBRepBuild/TopOpeBRepBuild_ffsfs.cxx +++ b/src/ModelingAlgorithms/TKBool/TopOpeBRepBuild/TopOpeBRepBuild_ffsfs.cxx @@ -51,8 +51,8 @@ Standard_EXPORT void debffflo(const int i) } #endif -static bool STATIC_motheropedef = false; -static TopOpeBRepBuild_GTopo STATIC_Gmotherope; +static thread_local bool STATIC_motheropedef = false; +static thread_local TopOpeBRepBuild_GTopo STATIC_Gmotherope; Standard_EXPORT void FUN_setmotherope(const TopOpeBRepBuild_GTopo& G) { diff --git a/src/ModelingAlgorithms/TKBool/TopOpeBRepDS/TopOpeBRepDS_CurveExplorer.cxx b/src/ModelingAlgorithms/TKBool/TopOpeBRepDS/TopOpeBRepDS_CurveExplorer.cxx index 33131d8915..343b50b755 100644 --- a/src/ModelingAlgorithms/TKBool/TopOpeBRepDS/TopOpeBRepDS_CurveExplorer.cxx +++ b/src/ModelingAlgorithms/TKBool/TopOpeBRepDS/TopOpeBRepDS_CurveExplorer.cxx @@ -19,7 +19,7 @@ #include #define MYDS (*((TopOpeBRepDS_DataStructure*)myDS)) -static TopOpeBRepDS_Curve* CEX_PEMPTY = nullptr; +static thread_local TopOpeBRepDS_Curve* CEX_PEMPTY = nullptr; //================================================================================================= diff --git a/src/ModelingAlgorithms/TKBool/TopOpeBRepDS/TopOpeBRepDS_FaceInterferenceTool.cxx b/src/ModelingAlgorithms/TKBool/TopOpeBRepDS/TopOpeBRepDS_FaceInterferenceTool.cxx index 51c63d0cdd..e6fd1ee632 100644 --- a/src/ModelingAlgorithms/TKBool/TopOpeBRepDS/TopOpeBRepDS_FaceInterferenceTool.cxx +++ b/src/ModelingAlgorithms/TKBool/TopOpeBRepDS/TopOpeBRepDS_FaceInterferenceTool.cxx @@ -32,7 +32,7 @@ #include #include -static bool STATIC_TOREVERSE = false; // xpu150498 +static thread_local bool STATIC_TOREVERSE = false; // xpu150498 #define M_FORWARD(ori) (ori == TopAbs_FORWARD) #define M_REVERSED(ori) (ori == TopAbs_REVERSED) diff --git a/src/ModelingAlgorithms/TKBool/TopOpeBRepDS/TopOpeBRepDS_connex.cxx b/src/ModelingAlgorithms/TKBool/TopOpeBRepDS/TopOpeBRepDS_connex.cxx index c0431f1fd6..a0f4b7edfb 100644 --- a/src/ModelingAlgorithms/TKBool/TopOpeBRepDS/TopOpeBRepDS_connex.cxx +++ b/src/ModelingAlgorithms/TKBool/TopOpeBRepDS/TopOpeBRepDS_connex.cxx @@ -19,14 +19,21 @@ #include #include -static NCollection_DataMap, TopTools_ShapeMapHasher>* - GLOBAL_elf1 = nullptr; // NYI to CDLize as a tool of DS -static NCollection_DataMap, TopTools_ShapeMapHasher>* - GLOBAL_elf2 = nullptr; // NYI to CDLize as a tool of DS -static NCollection_DataMap, TopTools_ShapeMapHasher>* - GLOBAL_fle = nullptr; // NYI to CDLize as a tool of DS -static NCollection_List* GLOBAL_los = nullptr; // NYI to CDLize as a tool of DS -static bool GLOBAL_FDSCNX_prepared = false; +static thread_local NCollection_DataMap, + TopTools_ShapeMapHasher>* GLOBAL_elf1 = + nullptr; // NYI to CDLize as a tool of DS +static thread_local NCollection_DataMap, + TopTools_ShapeMapHasher>* GLOBAL_elf2 = + nullptr; // NYI to CDLize as a tool of DS +static thread_local NCollection_DataMap, + TopTools_ShapeMapHasher>* GLOBAL_fle = + nullptr; // NYI to CDLize as a tool of DS +static thread_local NCollection_List* GLOBAL_los = + nullptr; // NYI to CDLize as a tool of DS +static thread_local bool GLOBAL_FDSCNX_prepared = false; // modified by NIZNHY-PKV Sun Dec 15 17:41:43 2002 f //================================================================================================= diff --git a/src/ModelingAlgorithms/TKBool/TopOpeBRepTool/TopOpeBRepTool_2d.cxx b/src/ModelingAlgorithms/TKBool/TopOpeBRepTool/TopOpeBRepTool_2d.cxx index 9ee1975d8a..fe3dc1702c 100644 --- a/src/ModelingAlgorithms/TKBool/TopOpeBRepTool/TopOpeBRepTool_2d.cxx +++ b/src/ModelingAlgorithms/TKBool/TopOpeBRepTool/TopOpeBRepTool_2d.cxx @@ -41,18 +41,19 @@ Standard_EXPORT bool TopOpeBRepTool_GettraceC2D(); #endif // structure e -> C2D/F -static NCollection_DataMap, - TopTools_ShapeMapHasher>* GLOBAL_pmosloc2df = nullptr; -static int GLOBAL_C2D_i = 0; // DEB +static thread_local NCollection_DataMap, + TopTools_ShapeMapHasher>* GLOBAL_pmosloc2df = nullptr; +static thread_local int GLOBAL_C2D_i = 0; // DEB // structure ancetre -static NCollection_IndexedDataMap, - TopTools_ShapeMapHasher>* GLOBAL_pidmoslosc2df = nullptr; -static TopoDS_Face* GLOBAL_pFc2df = nullptr; -static TopoDS_Shape* GLOBAL_pS1c2df = nullptr; -static TopoDS_Shape* GLOBAL_pS2c2df = nullptr; +static thread_local NCollection_IndexedDataMap, + TopTools_ShapeMapHasher>* GLOBAL_pidmoslosc2df = + nullptr; +static thread_local TopoDS_Face* GLOBAL_pFc2df = nullptr; +static thread_local TopoDS_Shape* GLOBAL_pS1c2df = nullptr; +static thread_local TopoDS_Shape* GLOBAL_pS2c2df = nullptr; Standard_EXPORT occ::handle MakePCurve(const ProjLib_ProjectedCurve& PC); diff --git a/src/ModelingAlgorithms/TKBool/TopOpeBRepTool/TopOpeBRepTool_SC.cxx b/src/ModelingAlgorithms/TKBool/TopOpeBRepTool/TopOpeBRepTool_SC.cxx index 37a3dad312..ea89a57fa1 100644 --- a/src/ModelingAlgorithms/TKBool/TopOpeBRepTool/TopOpeBRepTool_SC.cxx +++ b/src/ModelingAlgorithms/TKBool/TopOpeBRepTool/TopOpeBRepTool_SC.cxx @@ -23,7 +23,7 @@ #include // ---------------------------------------------------------------------- -static TopOpeBRepTool_PShapeClassifier TopOpeBRepTool_PSC = nullptr; +static thread_local TopOpeBRepTool_PShapeClassifier TopOpeBRepTool_PSC = nullptr; Standard_EXPORT TopOpeBRepTool_ShapeClassifier& FSC_GetPSC() { diff --git a/src/ModelingAlgorithms/TKTopAlgo/BRepCheck/BRepCheck_Analyzer.cxx b/src/ModelingAlgorithms/TKTopAlgo/BRepCheck/BRepCheck_Analyzer.cxx index 4e08585957..5f915b4bfe 100644 --- a/src/ModelingAlgorithms/TKTopAlgo/BRepCheck/BRepCheck_Analyzer.cxx +++ b/src/ModelingAlgorithms/TKTopAlgo/BRepCheck/BRepCheck_Analyzer.cxx @@ -170,10 +170,11 @@ public: if (performwire) { - std::unique_lock aLock = - aFaceEdgeRes->GetMutex() - ? std::unique_lock(*aFaceEdgeRes->GetMutex()) - : std::unique_lock(); + std::unique_lock aLock(aFaceEdgeRes->myMutex, std::defer_lock); + if (aFaceEdgeRes->IsParallel()) + { + aLock.lock(); + } if (aFaceEdgeRes->IsStatusOnShape(aShape)) { NCollection_List::Iterator itl( @@ -219,9 +220,11 @@ public: if (orientofwires) { - std::unique_lock aLock = - aFaceWireRes->GetMutex() ? std::unique_lock(*aFaceWireRes->GetMutex()) - : std::unique_lock(); + std::unique_lock aLock(aFaceWireRes->myMutex, std::defer_lock); + if (aFaceWireRes->IsParallel()) + { + aLock.lock(); + } if (aFaceWireRes->IsStatusOnShape(aShape)) { const NCollection_List& aStatusList = diff --git a/src/ModelingAlgorithms/TKTopAlgo/BRepCheck/BRepCheck_Edge.cxx b/src/ModelingAlgorithms/TKTopAlgo/BRepCheck/BRepCheck_Edge.cxx index 0c30bf5b13..ee16c7125f 100644 --- a/src/ModelingAlgorithms/TKTopAlgo/BRepCheck/BRepCheck_Edge.cxx +++ b/src/ModelingAlgorithms/TKTopAlgo/BRepCheck/BRepCheck_Edge.cxx @@ -264,8 +264,11 @@ void BRepCheck_Edge::InContext(const TopoDS_Shape& S) { occ::handle>> aHList; { - std::unique_lock aLock = - myMutex ? std::unique_lock(*myMutex) : std::unique_lock(); + std::unique_lock aLock(myMutex, std::defer_lock); + if (myIsParallel) + { + aLock.lock(); + } if (myMap.IsBound(S)) { return; @@ -334,7 +337,7 @@ void BRepCheck_Edge::InContext(const TopoDS_Shape& S) NCollection_List>::Iterator itcr(TE->Curves()); constexpr double eps = Precision::PConfusion(); - const bool toRunParallel = myMutex != nullptr; + const bool toRunParallel = myIsParallel; while (itcr.More()) { const occ::handle& cr = itcr.Value(); @@ -578,8 +581,11 @@ bool BRepCheck_Edge::GeometricControls() const void BRepCheck_Edge::SetStatus(const BRepCheck_Status theStatus) { - std::unique_lock aLock = - myMutex ? std::unique_lock(*myMutex) : std::unique_lock(); + std::unique_lock aLock(myMutex, std::defer_lock); + if (myIsParallel) + { + aLock.lock(); + } BRepCheck::Add(*myMap(myShape), theStatus); } diff --git a/src/ModelingAlgorithms/TKTopAlgo/BRepCheck/BRepCheck_Face.cxx b/src/ModelingAlgorithms/TKTopAlgo/BRepCheck/BRepCheck_Face.cxx index 76adc5b1a2..b718c5730e 100644 --- a/src/ModelingAlgorithms/TKTopAlgo/BRepCheck/BRepCheck_Face.cxx +++ b/src/ModelingAlgorithms/TKTopAlgo/BRepCheck/BRepCheck_Face.cxx @@ -117,8 +117,11 @@ void BRepCheck_Face::InContext(const TopoDS_Shape& S) { occ::handle>> aHList; { - std::unique_lock aLock = - myMutex ? std::unique_lock(*myMutex) : std::unique_lock(); + std::unique_lock aLock(myMutex, std::defer_lock); + if (myIsParallel) + { + aLock.lock(); + } if (myMap.IsBound(S)) { return; @@ -167,8 +170,11 @@ BRepCheck_Status BRepCheck_Face::IntersectWires(const bool Update) { occ::handle>> aHList; { - std::unique_lock aLock = - myMutex ? std::unique_lock(*myMutex) : std::unique_lock(); + std::unique_lock aLock(myMutex, std::defer_lock); + if (myIsParallel) + { + aLock.lock(); + } aHList = myMap(myShape); } @@ -297,8 +303,11 @@ BRepCheck_Status BRepCheck_Face::ClassifyWires(const bool Update) { occ::handle>> aHList; { - std::unique_lock aLock = - myMutex ? std::unique_lock(*myMutex) : std::unique_lock(); + std::unique_lock aLock(myMutex, std::defer_lock); + if (myIsParallel) + { + aLock.lock(); + } aHList = myMap(myShape); } @@ -429,8 +438,11 @@ BRepCheck_Status BRepCheck_Face::OrientationOfWires(const bool Update) { occ::handle>> aHList; { - std::unique_lock aLock = - myMutex ? std::unique_lock(*myMutex) : std::unique_lock(); + std::unique_lock aLock(myMutex, std::defer_lock); + if (myIsParallel) + { + aLock.lock(); + } aHList = myMap(myShape); } @@ -546,8 +558,11 @@ BRepCheck_Status BRepCheck_Face::OrientationOfWires(const bool Update) void BRepCheck_Face::SetUnorientable() { - std::unique_lock aLock = - myMutex ? std::unique_lock(*myMutex) : std::unique_lock(); + std::unique_lock aLock(myMutex, std::defer_lock); + if (myIsParallel) + { + aLock.lock(); + } BRepCheck::Add(*myMap(myShape), BRepCheck_UnorientableShape); } @@ -555,8 +570,11 @@ void BRepCheck_Face::SetUnorientable() void BRepCheck_Face::SetStatus(const BRepCheck_Status theStatus) { - std::unique_lock aLock = - myMutex ? std::unique_lock(*myMutex) : std::unique_lock(); + std::unique_lock aLock(myMutex, std::defer_lock); + if (myIsParallel) + { + aLock.lock(); + } BRepCheck::Add(*myMap(myShape), theStatus); } diff --git a/src/ModelingAlgorithms/TKTopAlgo/BRepCheck/BRepCheck_Result.cxx b/src/ModelingAlgorithms/TKTopAlgo/BRepCheck/BRepCheck_Result.cxx index 3215d9abba..c717a03e33 100644 --- a/src/ModelingAlgorithms/TKTopAlgo/BRepCheck/BRepCheck_Result.cxx +++ b/src/ModelingAlgorithms/TKTopAlgo/BRepCheck/BRepCheck_Result.cxx @@ -45,8 +45,11 @@ void BRepCheck_Result::Init(const TopoDS_Shape& S) void BRepCheck_Result::SetFailStatus(const TopoDS_Shape& S) { - std::unique_lock aLock = - myMutex ? std::unique_lock(*myMutex) : std::unique_lock(); + std::unique_lock aLock(myMutex, std::defer_lock); + if (myIsParallel) + { + aLock.lock(); + } occ::handle>> aList; if (!myMap.Find(S, aList)) { @@ -79,13 +82,3 @@ void BRepCheck_Result::NextShapeInContext() myIter.Next(); } } - -//================================================================================================= - -void BRepCheck_Result::SetParallel(bool theIsParallel) -{ - if (theIsParallel && !myMutex) - { - myMutex = opencascade::make_unique(); - } -} diff --git a/src/ModelingAlgorithms/TKTopAlgo/BRepCheck/BRepCheck_Result.hxx b/src/ModelingAlgorithms/TKTopAlgo/BRepCheck/BRepCheck_Result.hxx index ced4e5a434..0ae6c0ca2c 100644 --- a/src/ModelingAlgorithms/TKTopAlgo/BRepCheck/BRepCheck_Result.hxx +++ b/src/ModelingAlgorithms/TKTopAlgo/BRepCheck/BRepCheck_Result.hxx @@ -26,8 +26,6 @@ #include #include #include -#include - #include class BRepCheck_Result : public Standard_Transient @@ -60,7 +58,11 @@ public: Standard_EXPORT void NextShapeInContext(); - Standard_EXPORT void SetParallel(bool theIsParallel); + //! Sets the parallel execution flag for sub-algorithms. + void SetParallel(const bool theIsParallel) { myIsParallel = theIsParallel; } + + //! Returns TRUE if sub-algorithms should use parallel execution. + bool IsParallel() const { return myIsParallel; } bool IsStatusOnShape(const TopoDS_Shape& theShape) const { return myMap.IsBound(theShape); } @@ -80,14 +82,12 @@ protected: TopoDS_Shape myShape; bool myMin; bool myBlind; + bool myIsParallel = false; NCollection_DataMap>), TopTools_ShapeMapHasher> - myMap; - mutable std::unique_ptr myMutex; - -private: - std::unique_ptr& GetMutex() { return myMutex; } + myMap; + mutable std::mutex myMutex; private: NCollection_DataMap>> aHList; { - std::unique_lock aLock = - myMutex ? std::unique_lock(*myMutex) : std::unique_lock(); + std::unique_lock aLock(myMutex, std::defer_lock); + if (myIsParallel) + { + aLock.lock(); + } if (myMap.IsBound(S)) { return; @@ -255,8 +258,11 @@ BRepCheck_Status BRepCheck_Shell::Closed(const bool Update) { occ::handle>> aHList; { - std::unique_lock aLock = - myMutex ? std::unique_lock(*myMutex) : std::unique_lock(); + std::unique_lock aLock(myMutex, std::defer_lock); + if (myIsParallel) + { + aLock.lock(); + } aHList = myMap(myShape); } @@ -438,8 +444,11 @@ BRepCheck_Status BRepCheck_Shell::Orientation(const bool Update) { occ::handle>> aHList; { - std::unique_lock aLock = - myMutex ? std::unique_lock(*myMutex) : std::unique_lock(); + std::unique_lock aLock(myMutex, std::defer_lock); + if (myIsParallel) + { + aLock.lock(); + } aHList = myMap(myShape); } NCollection_List& aStatusList = *aHList; @@ -837,8 +846,11 @@ BRepCheck_Status BRepCheck_Shell::Orientation(const bool Update) void BRepCheck_Shell::SetUnorientable() { - std::unique_lock aLock = - myMutex ? std::unique_lock(*myMutex) : std::unique_lock(); + std::unique_lock aLock(myMutex, std::defer_lock); + if (myIsParallel) + { + aLock.lock(); + } BRepCheck::Add(*myMap(myShape), BRepCheck_UnorientableShape); } @@ -853,8 +865,11 @@ bool BRepCheck_Shell::IsUnorientable() const occ::handle>> aHList; { - std::unique_lock aLock = - myMutex ? std::unique_lock(*myMutex) : std::unique_lock(); + std::unique_lock aLock(myMutex, std::defer_lock); + if (myIsParallel) + { + aLock.lock(); + } aHList = myMap(myShape); } NCollection_List& aStatusList = *aHList; diff --git a/src/ModelingAlgorithms/TKTopAlgo/BRepCheck/BRepCheck_Vertex.cxx b/src/ModelingAlgorithms/TKTopAlgo/BRepCheck/BRepCheck_Vertex.cxx index e6a7a3a952..3ad722f9af 100644 --- a/src/ModelingAlgorithms/TKTopAlgo/BRepCheck/BRepCheck_Vertex.cxx +++ b/src/ModelingAlgorithms/TKTopAlgo/BRepCheck/BRepCheck_Vertex.cxx @@ -67,8 +67,11 @@ void BRepCheck_Vertex::InContext(const TopoDS_Shape& S) { occ::handle>> aHList; { - std::unique_lock aLock = - myMutex ? std::unique_lock(*myMutex) : std::unique_lock(); + std::unique_lock aLock(myMutex, std::defer_lock); + if (myIsParallel) + { + aLock.lock(); + } if (myMap.IsBound(S)) { return; diff --git a/src/ModelingAlgorithms/TKTopAlgo/BRepCheck/BRepCheck_Wire.cxx b/src/ModelingAlgorithms/TKTopAlgo/BRepCheck/BRepCheck_Wire.cxx index e8af79503d..3093aba5ec 100644 --- a/src/ModelingAlgorithms/TKTopAlgo/BRepCheck/BRepCheck_Wire.cxx +++ b/src/ModelingAlgorithms/TKTopAlgo/BRepCheck/BRepCheck_Wire.cxx @@ -193,8 +193,11 @@ void BRepCheck_Wire::InContext(const TopoDS_Shape& S) { occ::handle>> aHList; { - std::unique_lock aLock = - myMutex ? std::unique_lock(*myMutex) : std::unique_lock(); + std::unique_lock aLock(myMutex, std::defer_lock); + if (myIsParallel) + { + aLock.lock(); + } if (myMap.IsBound(S)) { return; @@ -281,8 +284,11 @@ BRepCheck_Status BRepCheck_Wire::Closed(const bool Update) { occ::handle>> aHList; { - std::unique_lock aLock = - myMutex ? std::unique_lock(*myMutex) : std::unique_lock(); + std::unique_lock aLock(myMutex, std::defer_lock); + if (myIsParallel) + { + aLock.lock(); + } aHList = myMap(myShape); } @@ -516,8 +522,11 @@ BRepCheck_Status BRepCheck_Wire::Closed2d(const TopoDS_Face& theFace, const bool { occ::handle>> aHList; { - std::unique_lock aLock = - myMutex ? std::unique_lock(*myMutex) : std::unique_lock(); + std::unique_lock aLock(myMutex, std::defer_lock); + if (myIsParallel) + { + aLock.lock(); + } aHList = myMap(myShape); } NCollection_List& aStatusList = *aHList; @@ -694,8 +703,11 @@ BRepCheck_Status BRepCheck_Wire::Orientation(const TopoDS_Face& F, const bool Up BRepCheck_Status theOstat = Closed(); occ::handle>> aHList; { - std::unique_lock aLock = - myMutex ? std::unique_lock(*myMutex) : std::unique_lock(); + std::unique_lock aLock(myMutex, std::defer_lock); + if (myIsParallel) + { + aLock.lock(); + } aHList = myMap(myShape); } NCollection_List& aStatusList = *aHList; @@ -1036,8 +1048,11 @@ BRepCheck_Status BRepCheck_Wire::SelfIntersect(const TopoDS_Face& F, { occ::handle>> aHList; { - std::unique_lock aLock = - myMutex ? std::unique_lock(*myMutex) : std::unique_lock(); + std::unique_lock aLock(myMutex, std::defer_lock); + if (myIsParallel) + { + aLock.lock(); + } aHList = myMap(myShape); } NCollection_List& aStatusList = *aHList;