mirror of
https://github.com/Open-Cascade-SAS/OCCT.git
synced 2026-08-28 22:08:25 +08:00
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.
This commit is contained in:
@@ -170,10 +170,11 @@ public:
|
||||
|
||||
if (performwire)
|
||||
{
|
||||
std::unique_lock<std::mutex> aLock =
|
||||
aFaceEdgeRes->GetMutex()
|
||||
? std::unique_lock<std::mutex>(*aFaceEdgeRes->GetMutex())
|
||||
: std::unique_lock<std::mutex>();
|
||||
std::unique_lock<std::mutex> aLock(aFaceEdgeRes->myMutex, std::defer_lock);
|
||||
if (aFaceEdgeRes->IsParallel())
|
||||
{
|
||||
aLock.lock();
|
||||
}
|
||||
if (aFaceEdgeRes->IsStatusOnShape(aShape))
|
||||
{
|
||||
NCollection_List<BRepCheck_Status>::Iterator itl(
|
||||
@@ -219,9 +220,11 @@ public:
|
||||
|
||||
if (orientofwires)
|
||||
{
|
||||
std::unique_lock<std::mutex> aLock =
|
||||
aFaceWireRes->GetMutex() ? std::unique_lock<std::mutex>(*aFaceWireRes->GetMutex())
|
||||
: std::unique_lock<std::mutex>();
|
||||
std::unique_lock<std::mutex> aLock(aFaceWireRes->myMutex, std::defer_lock);
|
||||
if (aFaceWireRes->IsParallel())
|
||||
{
|
||||
aLock.lock();
|
||||
}
|
||||
if (aFaceWireRes->IsStatusOnShape(aShape))
|
||||
{
|
||||
const NCollection_List<BRepCheck_Status>& aStatusList =
|
||||
|
||||
@@ -264,8 +264,11 @@ void BRepCheck_Edge::InContext(const TopoDS_Shape& S)
|
||||
{
|
||||
occ::handle<NCollection_Shared<NCollection_List<BRepCheck_Status>>> aHList;
|
||||
{
|
||||
std::unique_lock<std::mutex> aLock =
|
||||
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
|
||||
std::unique_lock<std::mutex> 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<occ::handle<BRep_CurveRepresentation>>::Iterator itcr(TE->Curves());
|
||||
constexpr double eps = Precision::PConfusion();
|
||||
const bool toRunParallel = myMutex != nullptr;
|
||||
const bool toRunParallel = myIsParallel;
|
||||
while (itcr.More())
|
||||
{
|
||||
const occ::handle<BRep_CurveRepresentation>& cr = itcr.Value();
|
||||
@@ -578,8 +581,11 @@ bool BRepCheck_Edge::GeometricControls() const
|
||||
|
||||
void BRepCheck_Edge::SetStatus(const BRepCheck_Status theStatus)
|
||||
{
|
||||
std::unique_lock<std::mutex> aLock =
|
||||
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
|
||||
std::unique_lock<std::mutex> aLock(myMutex, std::defer_lock);
|
||||
if (myIsParallel)
|
||||
{
|
||||
aLock.lock();
|
||||
}
|
||||
BRepCheck::Add(*myMap(myShape), theStatus);
|
||||
}
|
||||
|
||||
|
||||
@@ -117,8 +117,11 @@ void BRepCheck_Face::InContext(const TopoDS_Shape& S)
|
||||
{
|
||||
occ::handle<NCollection_Shared<NCollection_List<BRepCheck_Status>>> aHList;
|
||||
{
|
||||
std::unique_lock<std::mutex> aLock =
|
||||
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
|
||||
std::unique_lock<std::mutex> 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<NCollection_Shared<NCollection_List<BRepCheck_Status>>> aHList;
|
||||
{
|
||||
std::unique_lock<std::mutex> aLock =
|
||||
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
|
||||
std::unique_lock<std::mutex> 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<NCollection_Shared<NCollection_List<BRepCheck_Status>>> aHList;
|
||||
{
|
||||
std::unique_lock<std::mutex> aLock =
|
||||
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
|
||||
std::unique_lock<std::mutex> 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<NCollection_Shared<NCollection_List<BRepCheck_Status>>> aHList;
|
||||
{
|
||||
std::unique_lock<std::mutex> aLock =
|
||||
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
|
||||
std::unique_lock<std::mutex> 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<std::mutex> aLock =
|
||||
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
|
||||
std::unique_lock<std::mutex> 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<std::mutex> aLock =
|
||||
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
|
||||
std::unique_lock<std::mutex> aLock(myMutex, std::defer_lock);
|
||||
if (myIsParallel)
|
||||
{
|
||||
aLock.lock();
|
||||
}
|
||||
BRepCheck::Add(*myMap(myShape), theStatus);
|
||||
}
|
||||
|
||||
|
||||
@@ -45,8 +45,11 @@ void BRepCheck_Result::Init(const TopoDS_Shape& S)
|
||||
|
||||
void BRepCheck_Result::SetFailStatus(const TopoDS_Shape& S)
|
||||
{
|
||||
std::unique_lock<std::mutex> aLock =
|
||||
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
|
||||
std::unique_lock<std::mutex> aLock(myMutex, std::defer_lock);
|
||||
if (myIsParallel)
|
||||
{
|
||||
aLock.lock();
|
||||
}
|
||||
occ::handle<NCollection_Shared<NCollection_List<BRepCheck_Status>>> 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<std::mutex>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,8 +26,6 @@
|
||||
#include <NCollection_Shared.hxx>
|
||||
#include <TopTools_ShapeMapHasher.hxx>
|
||||
#include <NCollection_DataMap.hxx>
|
||||
#include <Standard_MemoryUtils.hxx>
|
||||
|
||||
#include <mutex>
|
||||
|
||||
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<TopoDS_Shape,
|
||||
Handle(NCollection_Shared<NCollection_List<BRepCheck_Status>>),
|
||||
TopTools_ShapeMapHasher>
|
||||
myMap;
|
||||
mutable std::unique_ptr<std::mutex> myMutex;
|
||||
|
||||
private:
|
||||
std::unique_ptr<std::mutex>& GetMutex() { return myMutex; }
|
||||
myMap;
|
||||
mutable std::mutex myMutex;
|
||||
|
||||
private:
|
||||
NCollection_DataMap<TopoDS_Shape,
|
||||
|
||||
@@ -183,8 +183,11 @@ void BRepCheck_Shell::InContext(const TopoDS_Shape& S)
|
||||
{
|
||||
occ::handle<NCollection_Shared<NCollection_List<BRepCheck_Status>>> aHList;
|
||||
{
|
||||
std::unique_lock<std::mutex> aLock =
|
||||
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
|
||||
std::unique_lock<std::mutex> 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<NCollection_Shared<NCollection_List<BRepCheck_Status>>> aHList;
|
||||
{
|
||||
std::unique_lock<std::mutex> aLock =
|
||||
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
|
||||
std::unique_lock<std::mutex> 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<NCollection_Shared<NCollection_List<BRepCheck_Status>>> aHList;
|
||||
{
|
||||
std::unique_lock<std::mutex> aLock =
|
||||
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
|
||||
std::unique_lock<std::mutex> aLock(myMutex, std::defer_lock);
|
||||
if (myIsParallel)
|
||||
{
|
||||
aLock.lock();
|
||||
}
|
||||
aHList = myMap(myShape);
|
||||
}
|
||||
NCollection_List<BRepCheck_Status>& aStatusList = *aHList;
|
||||
@@ -837,8 +846,11 @@ BRepCheck_Status BRepCheck_Shell::Orientation(const bool Update)
|
||||
|
||||
void BRepCheck_Shell::SetUnorientable()
|
||||
{
|
||||
std::unique_lock<std::mutex> aLock =
|
||||
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
|
||||
std::unique_lock<std::mutex> 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<NCollection_Shared<NCollection_List<BRepCheck_Status>>> aHList;
|
||||
{
|
||||
std::unique_lock<std::mutex> aLock =
|
||||
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
|
||||
std::unique_lock<std::mutex> aLock(myMutex, std::defer_lock);
|
||||
if (myIsParallel)
|
||||
{
|
||||
aLock.lock();
|
||||
}
|
||||
aHList = myMap(myShape);
|
||||
}
|
||||
NCollection_List<BRepCheck_Status>& aStatusList = *aHList;
|
||||
|
||||
@@ -67,8 +67,11 @@ void BRepCheck_Vertex::InContext(const TopoDS_Shape& S)
|
||||
{
|
||||
occ::handle<NCollection_Shared<NCollection_List<BRepCheck_Status>>> aHList;
|
||||
{
|
||||
std::unique_lock<std::mutex> aLock =
|
||||
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
|
||||
std::unique_lock<std::mutex> aLock(myMutex, std::defer_lock);
|
||||
if (myIsParallel)
|
||||
{
|
||||
aLock.lock();
|
||||
}
|
||||
if (myMap.IsBound(S))
|
||||
{
|
||||
return;
|
||||
|
||||
@@ -193,8 +193,11 @@ void BRepCheck_Wire::InContext(const TopoDS_Shape& S)
|
||||
{
|
||||
occ::handle<NCollection_Shared<NCollection_List<BRepCheck_Status>>> aHList;
|
||||
{
|
||||
std::unique_lock<std::mutex> aLock =
|
||||
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
|
||||
std::unique_lock<std::mutex> 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<NCollection_Shared<NCollection_List<BRepCheck_Status>>> aHList;
|
||||
{
|
||||
std::unique_lock<std::mutex> aLock =
|
||||
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
|
||||
std::unique_lock<std::mutex> 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<NCollection_Shared<NCollection_List<BRepCheck_Status>>> aHList;
|
||||
{
|
||||
std::unique_lock<std::mutex> aLock =
|
||||
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
|
||||
std::unique_lock<std::mutex> aLock(myMutex, std::defer_lock);
|
||||
if (myIsParallel)
|
||||
{
|
||||
aLock.lock();
|
||||
}
|
||||
aHList = myMap(myShape);
|
||||
}
|
||||
NCollection_List<BRepCheck_Status>& aStatusList = *aHList;
|
||||
@@ -694,8 +703,11 @@ BRepCheck_Status BRepCheck_Wire::Orientation(const TopoDS_Face& F, const bool Up
|
||||
BRepCheck_Status theOstat = Closed();
|
||||
occ::handle<NCollection_Shared<NCollection_List<BRepCheck_Status>>> aHList;
|
||||
{
|
||||
std::unique_lock<std::mutex> aLock =
|
||||
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
|
||||
std::unique_lock<std::mutex> aLock(myMutex, std::defer_lock);
|
||||
if (myIsParallel)
|
||||
{
|
||||
aLock.lock();
|
||||
}
|
||||
aHList = myMap(myShape);
|
||||
}
|
||||
NCollection_List<BRepCheck_Status>& aStatusList = *aHList;
|
||||
@@ -1036,8 +1048,11 @@ BRepCheck_Status BRepCheck_Wire::SelfIntersect(const TopoDS_Face& F,
|
||||
{
|
||||
occ::handle<NCollection_Shared<NCollection_List<BRepCheck_Status>>> aHList;
|
||||
{
|
||||
std::unique_lock<std::mutex> aLock =
|
||||
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
|
||||
std::unique_lock<std::mutex> aLock(myMutex, std::defer_lock);
|
||||
if (myIsParallel)
|
||||
{
|
||||
aLock.lock();
|
||||
}
|
||||
aHList = myMap(myShape);
|
||||
}
|
||||
NCollection_List<BRepCheck_Status>& aStatusList = *aHList;
|
||||
|
||||
Reference in New Issue
Block a user