Coding - Replace Standard_Mutex with std::mutex and migrate to RAII locks (#766)

- Replace legacy Standard_Mutex usage across many modules with std::mutex.
- Include <mutex> where needed and remove <Standard_Mutex.hxx> includes.
- Replace Standard_Mutex::Sentry / explicit Lock/Unlock with std::lock_guard or std::unique_lock.
- Convert optional/heap mutex holders to std::unique_ptr<std::mutex> and adapt locking accordingly.
- Simplify several singleton initializations (remove manual double-checked locking where safe).
- Use thread_local for per-thread flags instead of ad-hoc mutex protection.
- Fix BVH_BuildQueue Fetch logic to preserve thread counters and wasBusy handling.
- Remove obsolete TopTools_MutexForShapeProvider sources and update FILES.cmake.

This modernizes mutex usage, reduces dependency on custom mutex types and improves clarity of locking patterns.
This commit is contained in:
Pasukhin Dmitry
2025-11-03 16:44:08 +00:00
committed by GitHub
parent d98f74d893
commit 787bee375c
95 changed files with 562 additions and 568 deletions
@@ -33,6 +33,7 @@
#include <NCollection_Vector.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <Standard_ErrorHandler.hxx>
#include <TopoDS_Vertex.hxx>
//=================================================================================================
@@ -31,6 +31,7 @@
#include <BOPTools_Parallel.hxx>
#include <BndLib_Add3dCurve.hxx>
#include <BRep_Builder.hxx>
#include <Standard_ErrorHandler.hxx>
#include <GeomAPI_ProjectPointOnCurve.hxx>
#include <gp_Pnt.hxx>
#include <IntTools_CommonPrt.hxx>
@@ -26,6 +26,7 @@
#include <BOPDS_VectorOfInterfVF.hxx>
#include <BOPTools_Parallel.hxx>
#include <IntTools_Context.hxx>
#include <Standard_ErrorHandler.hxx>
#include <NCollection_Vector.hxx>
#include <TColStd_MapOfInteger.hxx>
#include <TopoDS_Face.hxx>
@@ -32,6 +32,7 @@
#include <BOPTools_Parallel.hxx>
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <Standard_ErrorHandler.hxx>
#include <GeomAPI_ProjectPointOnSurf.hxx>
#include <gp_Pnt.hxx>
#include <IntTools_CommonPrt.hxx>
@@ -56,6 +56,7 @@
#include <gp_Pnt.hxx>
#include <IntSurf_ListOfPntOn2S.hxx>
#include <IntSurf_PntOn2S.hxx>
#include <Standard_ErrorHandler.hxx>
#include <IntTools.hxx>
#include <IntTools_Context.hxx>
#include <IntTools_Curve.hxx>
@@ -45,6 +45,7 @@
#include <Geom_Curve.hxx>
#include <Geom_Plane.hxx>
#include <Geom_RectangularTrimmedSurface.hxx>
#include <Standard_ErrorHandler.hxx>
#include <Geom_Surface.hxx>
#include <GeomAPI_ProjectPointOnCurve.hxx>
#include <GeomAPI_ProjectPointOnSurf.hxx>
@@ -20,6 +20,7 @@
#include <BOPAlgo_BuilderSolid.hxx>
#include <BOPAlgo_MakerVolume.hxx>
#include <BOPAlgo_Tools.hxx>
#include <Standard_ErrorHandler.hxx>
#include <BOPTools_AlgoTools.hxx>
#include <BOPTools_Parallel.hxx>
@@ -18,9 +18,10 @@
#include <OSD_Parallel.hxx>
#include <OSD_ThreadPool.hxx>
#include <NCollection_DataMap.hxx>
#include <Standard_Mutex.hxx>
#include <OSD_Thread.hxx>
#include <mutex>
//! Implementation of Functors/Starters
class BOPTools_Parallel
{
@@ -82,7 +83,7 @@ class BOPTools_Parallel
opencascade::handle<TypeContext> aContext =
new TypeContext(NCollection_BaseAllocator::CommonBaseAllocator());
Standard_Mutex::Sentry aLocker(myMutex);
std::lock_guard<std::mutex> aLock(myMutex);
myContextMap.Bind(aThreadID, aContext);
return myContextMap(aThreadID);
}
@@ -104,7 +105,7 @@ class BOPTools_Parallel
private:
TypeSolverVector& mySolverVector;
mutable NCollection_DataMap<Standard_ThreadId, opencascade::handle<TypeContext>> myContextMap;
mutable Standard_Mutex myMutex;
mutable std::mutex myMutex;
};
//! Functor storing array of algorithm contexts per thread in pool
@@ -17,6 +17,7 @@
#define _IMeshTools_ModelAlgo_HeaderFile
#include <Standard_Transient.hxx>
#include <Standard_ErrorHandler.hxx>
#include <Message_ProgressRange.hxx>
class IMeshData_Model;
@@ -29,6 +29,7 @@
#include <ShapeAnalysis_Curve.hxx>
#include <ShapeAnalysis_Edge.hxx>
#include <ShapeAnalysis_Surface.hxx>
#include <Standard_ErrorHandler.hxx>
#include <Geom_TrimmedCurve.hxx>
#include <gp_Pln.hxx>
#include <GeomAdaptor_Surface.hxx>
@@ -19,15 +19,23 @@
#include <ShapeProcess_Context.hxx>
#include <Standard_ErrorHandler.hxx>
#include <Standard_Failure.hxx>
#include <Standard_Mutex.hxx>
#include <Standard_Type.hxx>
#include <TCollection_AsciiString.hxx>
#include <TCollection_HAsciiString.hxx>
#include <mutex>
#include <sys/stat.h>
IMPLEMENT_STANDARD_RTTIEXT(ShapeProcess_Context, Standard_Transient)
static Standard_Mutex THE_SHAPE_PROCESS_MUTEX;
namespace
{
static std::mutex& GetShapeProcessMutex()
{
static std::mutex THE_SHAPE_PROCESS_MUTEX;
return THE_SHAPE_PROCESS_MUTEX;
}
} // namespace
//=================================================================================================
@@ -74,7 +82,7 @@ Handle(Resource_Manager) ShapeProcess_Context::LoadResourceManager(const Standar
{
// Mutex is needed because we are initializing and changing static variables here, so
// without mutex it leads to race condition.
Standard_Mutex::Sentry aLock(&THE_SHAPE_PROCESS_MUTEX);
std::lock_guard<std::mutex> aLock(GetShapeProcessMutex());
// Optimisation of loading resource file: file is load only once
// and reloaded only if file date has changed
static Handle(Resource_Manager) sRC;
@@ -29,7 +29,6 @@
#include <OSD_Parallel.hxx>
#include <Standard_ErrorHandler.hxx>
#include <Standard_Failure.hxx>
#include <Standard_Mutex.hxx>
#include <Standard_NullObject.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
@@ -37,6 +36,8 @@
#include <TopoDS_Shape.hxx>
#include <TopTools_MapOfShape.hxx>
#include <mutex>
//! Functor for multi-threaded execution.
class BRepCheck_ParallelAnalyzer
{
@@ -166,7 +167,10 @@ public:
if (performwire)
{
Standard_Mutex::Sentry aLock(aFaceEdgeRes->GetMutex());
std::unique_lock<std::mutex> aLock =
aFaceEdgeRes->GetMutex()
? std::unique_lock<std::mutex>(*aFaceEdgeRes->GetMutex())
: std::unique_lock<std::mutex>();
if (aFaceEdgeRes->IsStatusOnShape(aShape))
{
BRepCheck_ListIteratorOfListOfStatus itl(aFaceEdgeRes->StatusOnShape(aShape));
@@ -211,7 +215,9 @@ public:
if (orientofwires)
{
Standard_Mutex::Sentry aLock(aFaceWireRes->GetMutex());
std::unique_lock<std::mutex> aLock =
aFaceWireRes->GetMutex() ? std::unique_lock<std::mutex>(*aFaceWireRes->GetMutex())
: std::unique_lock<std::mutex>();
if (aFaceWireRes->IsStatusOnShape(aShape))
{
const BRepCheck_ListOfStatus& aStatusList = aFaceWireRes->StatusOnShape(aShape);
@@ -259,7 +259,8 @@ void BRepCheck_Edge::InContext(const TopoDS_Shape& S)
{
Handle(BRepCheck_HListOfStatus) aHList;
{
Standard_Mutex::Sentry aLock(myMutex.get());
std::unique_lock<std::mutex> aLock =
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
if (myMap.IsBound(S))
{
return;
@@ -327,7 +328,7 @@ void BRepCheck_Edge::InContext(const TopoDS_Shape& S)
BRep_ListIteratorOfListOfCurveRepresentation itcr(TE->Curves());
constexpr Standard_Real eps = Precision::PConfusion();
Standard_Boolean toRunParallel = !myMutex.IsNull();
const Standard_Boolean toRunParallel = myMutex != nullptr;
while (itcr.More())
{
const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
@@ -571,7 +572,8 @@ Standard_Boolean BRepCheck_Edge::GeometricControls() const
void BRepCheck_Edge::SetStatus(const BRepCheck_Status theStatus)
{
Standard_Mutex::Sentry aLock(myMutex.get());
std::unique_lock<std::mutex> aLock =
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
BRepCheck::Add(*myMap(myShape), theStatus);
}
@@ -115,7 +115,8 @@ void BRepCheck_Face::InContext(const TopoDS_Shape& S)
{
Handle(BRepCheck_HListOfStatus) aHList;
{
Standard_Mutex::Sentry aLock(myMutex.get());
std::unique_lock<std::mutex> aLock =
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
if (myMap.IsBound(S))
{
return;
@@ -163,7 +164,8 @@ BRepCheck_Status BRepCheck_Face::IntersectWires(const Standard_Boolean Update)
{
Handle(BRepCheck_HListOfStatus) aHList;
{
Standard_Mutex::Sentry aLock(myMutex.get());
std::unique_lock<std::mutex> aLock =
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
aHList = myMap(myShape);
}
@@ -292,7 +294,8 @@ BRepCheck_Status BRepCheck_Face::ClassifyWires(const Standard_Boolean Update)
{
Handle(BRepCheck_HListOfStatus) aHList;
{
Standard_Mutex::Sentry aLock(myMutex.get());
std::unique_lock<std::mutex> aLock =
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
aHList = myMap(myShape);
}
@@ -420,7 +423,8 @@ BRepCheck_Status BRepCheck_Face::OrientationOfWires(const Standard_Boolean Updat
{
Handle(BRepCheck_HListOfStatus) aHList;
{
Standard_Mutex::Sentry aLock(myMutex.get());
std::unique_lock<std::mutex> aLock =
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
aHList = myMap(myShape);
}
@@ -535,7 +539,8 @@ BRepCheck_Status BRepCheck_Face::OrientationOfWires(const Standard_Boolean Updat
void BRepCheck_Face::SetUnorientable()
{
Standard_Mutex::Sentry aLock(myMutex.get());
std::unique_lock<std::mutex> aLock =
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
BRepCheck::Add(*myMap(myShape), BRepCheck_UnorientableShape);
}
@@ -543,7 +548,8 @@ void BRepCheck_Face::SetUnorientable()
void BRepCheck_Face::SetStatus(const BRepCheck_Status theStatus)
{
Standard_Mutex::Sentry aLock(myMutex.get());
std::unique_lock<std::mutex> aLock =
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
BRepCheck::Add(*myMap(myShape), theStatus);
}
@@ -46,7 +46,8 @@ void BRepCheck_Result::Init(const TopoDS_Shape& S)
void BRepCheck_Result::SetFailStatus(const TopoDS_Shape& S)
{
Standard_Mutex::Sentry aLock(myMutex.get());
std::unique_lock<std::mutex> aLock =
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
Handle(BRepCheck_HListOfStatus) aList;
if (!myMap.Find(S, aList))
{
@@ -84,8 +85,8 @@ void BRepCheck_Result::NextShapeInContext()
void BRepCheck_Result::SetParallel(Standard_Boolean theIsParallel)
{
if (theIsParallel && myMutex.IsNull())
if (theIsParallel && !myMutex)
{
myMutex.reset(new Standard_HMutex());
myMutex = opencascade::make_unique<std::mutex>();
}
}
@@ -19,10 +19,12 @@
#include <Standard.hxx>
#include <Standard_Mutex.hxx>
#include <Standard_Transient.hxx>
#include <BRepCheck_DataMapOfShapeListOfStatus.hxx>
#include <BRepCheck_ListOfStatus.hxx>
#include <Standard_MemoryUtils.hxx>
#include <mutex>
DEFINE_STANDARD_HANDLE(BRepCheck_Result, Standard_Transient)
@@ -80,10 +82,10 @@ protected:
Standard_Boolean myMin;
Standard_Boolean myBlind;
BRepCheck_DataMapOfShapeListOfStatus myMap;
mutable Handle(Standard_HMutex) myMutex;
mutable std::unique_ptr<std::mutex> myMutex;
private:
Standard_HMutex* GetMutex() { return myMutex.get(); }
std::unique_ptr<std::mutex>& GetMutex() { return myMutex; }
private:
BRepCheck_DataMapIteratorOfDataMapOfShapeListOfStatus myIter;
@@ -177,7 +177,8 @@ void BRepCheck_Shell::InContext(const TopoDS_Shape& S)
{
Handle(BRepCheck_HListOfStatus) aHList;
{
Standard_Mutex::Sentry aLock(myMutex.get());
std::unique_lock<std::mutex> aLock =
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
if (myMap.IsBound(S))
{
return;
@@ -247,7 +248,8 @@ BRepCheck_Status BRepCheck_Shell::Closed(const Standard_Boolean Update)
{
Handle(BRepCheck_HListOfStatus) aHList;
{
Standard_Mutex::Sentry aLock(myMutex.get());
std::unique_lock<std::mutex> aLock =
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
aHList = myMap(myShape);
}
@@ -429,7 +431,8 @@ BRepCheck_Status BRepCheck_Shell::Orientation(const Standard_Boolean Update)
{
Handle(BRepCheck_HListOfStatus) aHList;
{
Standard_Mutex::Sentry aLock(myMutex.get());
std::unique_lock<std::mutex> aLock =
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
aHList = myMap(myShape);
}
BRepCheck_ListOfStatus& aStatusList = *aHList;
@@ -826,7 +829,8 @@ BRepCheck_Status BRepCheck_Shell::Orientation(const Standard_Boolean Update)
void BRepCheck_Shell::SetUnorientable()
{
Standard_Mutex::Sentry aLock(myMutex.get());
std::unique_lock<std::mutex> aLock =
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
BRepCheck::Add(*myMap(myShape), BRepCheck_UnorientableShape);
}
@@ -841,7 +845,8 @@ Standard_Boolean BRepCheck_Shell::IsUnorientable() const
Handle(BRepCheck_HListOfStatus) aHList;
{
Standard_Mutex::Sentry aLock(myMutex.get());
std::unique_lock<std::mutex> aLock =
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
aHList = myMap(myShape);
}
BRepCheck_ListOfStatus& aStatusList = *aHList;
@@ -64,7 +64,8 @@ void BRepCheck_Vertex::InContext(const TopoDS_Shape& S)
{
Handle(BRepCheck_HListOfStatus) aHList;
{
Standard_Mutex::Sentry aLock(myMutex.get());
std::unique_lock<std::mutex> aLock =
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
if (myMap.IsBound(S))
{
return;
@@ -187,7 +187,8 @@ void BRepCheck_Wire::InContext(const TopoDS_Shape& S)
{
Handle(BRepCheck_HListOfStatus) aHList;
{
Standard_Mutex::Sentry aLock(myMutex.get());
std::unique_lock<std::mutex> aLock =
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
if (myMap.IsBound(S))
{
return;
@@ -273,7 +274,8 @@ BRepCheck_Status BRepCheck_Wire::Closed(const Standard_Boolean Update)
{
Handle(BRepCheck_HListOfStatus) aHList;
{
Standard_Mutex::Sentry aLock(myMutex.get());
std::unique_lock<std::mutex> aLock =
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
aHList = myMap(myShape);
}
@@ -540,7 +542,8 @@ BRepCheck_Status BRepCheck_Wire::Closed2d(const TopoDS_Face& theFace, const Stan
{
Handle(BRepCheck_HListOfStatus) aHList;
{
Standard_Mutex::Sentry aLock(myMutex.get());
std::unique_lock<std::mutex> aLock =
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
aHList = myMap(myShape);
}
BRepCheck_ListOfStatus& aStatusList = *aHList;
@@ -717,7 +720,8 @@ BRepCheck_Status BRepCheck_Wire::Orientation(const TopoDS_Face& F, const Standar
BRepCheck_Status theOstat = Closed();
Handle(BRepCheck_HListOfStatus) aHList;
{
Standard_Mutex::Sentry aLock(myMutex.get());
std::unique_lock<std::mutex> aLock =
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
aHList = myMap(myShape);
}
BRepCheck_ListOfStatus& aStatusList = *aHList;
@@ -1057,7 +1061,8 @@ BRepCheck_Status BRepCheck_Wire::SelfIntersect(const TopoDS_Face& F,
{
Handle(BRepCheck_HListOfStatus) aHList;
{
Standard_Mutex::Sentry aLock(myMutex.get());
std::unique_lock<std::mutex> aLock =
myMutex ? std::unique_lock<std::mutex>(*myMutex) : std::unique_lock<std::mutex>();
aHList = myMap(myShape);
}
BRepCheck_ListOfStatus& aStatusList = *aHList;
@@ -28,6 +28,7 @@
#include <TopoDS_Vertex.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <Standard_MemoryUtils.hxx>
#include <TopAbs_ShapeEnum.hxx>
#include <Precision.hxx>
#include <BRepExtrema_UnCompatibleShape.hxx>
@@ -38,6 +39,8 @@
#include <StdFail_NotDone.hxx>
#include <algorithm>
#include <atomic>
#include <mutex>
namespace
{
@@ -696,7 +699,7 @@ struct TreatmentFunctor
DistRef(0),
InnerSol(NULL),
IsDone(NULL),
Mutex(NULL)
Mutex()
{
for (Standard_Integer i = 0; i < theArrayOfArrays->Size(); ++i)
{
@@ -717,7 +720,7 @@ struct TreatmentFunctor
break;
}
aScope.Next();
if (*IsDone)
if (IsDone->load(std::memory_order_acquire))
{
break;
}
@@ -727,10 +730,11 @@ struct TreatmentFunctor
aClassifier.Perform(aPnt, aTolerance);
if (aClassifier.State() == TopAbs_IN)
{
Standard_Mutex::Sentry aLock(Mutex.get());
*InnerSol = Standard_True;
*DistRef = 0.;
*IsDone = Standard_True;
std::unique_lock<std::mutex> aLock =
Mutex ? std::unique_lock<std::mutex>(*Mutex) : std::unique_lock<std::mutex>();
InnerSol->store(true, std::memory_order_release);
*DistRef = 0.;
IsDone->store(true, std::memory_order_release);
BRepExtrema_SolutionElem aSolElem(0, aPnt, BRepExtrema_IsVertex, aVertex);
SolutionsShape1->Append(aSolElem);
SolutionsShape2->Append(aSolElem);
@@ -746,9 +750,9 @@ struct TreatmentFunctor
Message_ProgressScope Scope;
NCollection_Array1<Message_ProgressRange> Ranges;
Standard_Real* DistRef;
volatile Standard_Boolean* InnerSol;
volatile Standard_Boolean* IsDone;
Handle(Standard_HMutex) Mutex;
std::atomic<bool>* InnerSol;
std::atomic<bool>* IsDone;
std::unique_ptr<std::mutex> Mutex;
};
//=================================================================================================
@@ -788,21 +792,29 @@ Standard_Boolean BRepExtrema_DistShapeShape::SolidTreatment(
anArrayOfArray[aVectIndex][aShapeIndex] = theVertexMap(anI);
}
// Create local atomic variables for thread-safe communication during parallel section
std::atomic<bool> anAtomicInnerSol(myInnerSol);
std::atomic<bool> anAtomicIsDone(myIsDone);
Message_ProgressScope aScope(theRange, "Solid treatment", aNbTasks);
TreatmentFunctor aFunctor(&anArrayOfArray, aScope.Next());
aFunctor.SolutionsShape1 = &mySolutionsShape1;
aFunctor.SolutionsShape2 = &mySolutionsShape2;
aFunctor.Shape = theShape;
aFunctor.DistRef = &myDistRef;
aFunctor.InnerSol = &myInnerSol;
aFunctor.IsDone = &myIsDone;
if (myIsMultiThread)
aFunctor.InnerSol = &anAtomicInnerSol;
aFunctor.IsDone = &anAtomicIsDone;
if (myIsMultiThread && !aFunctor.Mutex)
{
aFunctor.Mutex.reset(new Standard_HMutex());
aFunctor.Mutex = std::make_unique<std::mutex>();
}
OSD_Parallel::For(0, aNbTasks, aFunctor, !myIsMultiThread);
// Copy atomic results back to class members after parallel section completes
myInnerSol = anAtomicInnerSol.load(std::memory_order_acquire);
myIsDone = anAtomicIsDone.load(std::memory_order_acquire);
if (!aScope.More())
{
return Standard_False;