diff --git a/src/BRepMesh/BRepMesh_FastDiscret.cdl b/src/BRepMesh/BRepMesh_FastDiscret.cdl index 183a8815a0..7affa55075 100755 --- a/src/BRepMesh/BRepMesh_FastDiscret.cdl +++ b/src/BRepMesh/BRepMesh_FastDiscret.cdl @@ -67,8 +67,9 @@ uses Boolean from Standard, MapOfInteger from BRepMesh, BaseAllocator from BRepMesh, DataMapOfFaceAttribute from BRepMesh, - IndexedDataMapOfShapeListOfShape from TopTools - + IndexedDataMapOfShapeListOfShape from TopTools, + MutexForShapeProvider from TopTools, + ShapeEnum from TopAbs is @@ -193,6 +194,17 @@ is returns Boolean from Standard; ---Purpose: -- Returns the multi-threading usage flag. + + CreateMutexesForSubShapes(me : mutable; + theShape : Shape from TopoDS; + theType : ShapeEnum from TopAbs); + ---Purpose: + -- Creates mutexes for each sub-shape of type theType in theShape. + -- Used to avoid data races. + + RemoveAllMutexes(me: mutable); + ---Purpose: + -- Removes all created mutexes -- Output : @@ -338,5 +350,6 @@ fields myMapdefle : DataMapOfShapeReal from TopTools; myNottriangulated : ListOfShape from TopTools; myAllocator : BaseAllocator from BRepMesh; + myMutexProvider: MutexForShapeProvider from TopTools; end FastDiscret; diff --git a/src/BRepMesh/BRepMesh_FastDiscret.cxx b/src/BRepMesh/BRepMesh_FastDiscret.cxx index 2d8dcde81a..1d4d9273d6 100755 --- a/src/BRepMesh/BRepMesh_FastDiscret.cxx +++ b/src/BRepMesh/BRepMesh_FastDiscret.cxx @@ -258,6 +258,7 @@ void BRepMesh_FastDiscret::Perform(const TopoDS_Shape& theShape) if (myInParallel) { #ifdef HAVE_TBB + CreateMutexesForSubShapes(theShape, TopAbs_EDGE); // mesh faces in parallel threads using TBB tbb::parallel_for_each (aFaces.begin(), aFaces.end(), *this); #else @@ -265,6 +266,7 @@ void BRepMesh_FastDiscret::Perform(const TopoDS_Shape& theShape) for (std::vector::iterator it(aFaces.begin()); it != aFaces.end(); it++) Process (*it); #endif + RemoveAllMutexes(); } else { @@ -286,7 +288,7 @@ void BRepMesh_FastDiscret::Process(const TopoDS_Face& theFace) const if ( GetFaceAttribute (theFace, fattribute) ) { BRepMesh_FastDiscretFace aTool (GetAngle(), WithShare()); - aTool.Add (theFace, fattribute, GetMapOfDefEdge()); + aTool.Add (theFace, fattribute, GetMapOfDefEdge(), myMutexProvider); } //cout << "END face " << theFace.TShape().operator->() << endl << flush; } @@ -1687,3 +1689,22 @@ void BRepMesh_FastDiscret::RemoveFaceAttribute(const TopoDS_Face& theFace) if(myMapattrib.IsBound(theFace)) myMapattrib.UnBind(theFace); } + +//======================================================================= +//function : CreateMutexesForSubShapes +//purpose : +//======================================================================= +void BRepMesh_FastDiscret::CreateMutexesForSubShapes(const TopoDS_Shape& theShape, + const TopAbs_ShapeEnum theType) +{ + myMutexProvider.CreateMutexesForSubShapes(theShape, theType); +} + +//======================================================================= +//function : RemoveAllMutexes +//purpose : +//======================================================================= +void BRepMesh_FastDiscret::RemoveAllMutexes() +{ + myMutexProvider.RemoveAllMutexes(); +} \ No newline at end of file diff --git a/src/BRepMesh/BRepMesh_FastDiscretFace.cdl b/src/BRepMesh/BRepMesh_FastDiscretFace.cdl index 3930b32a4d..53e2c69326 100755 --- a/src/BRepMesh/BRepMesh_FastDiscretFace.cdl +++ b/src/BRepMesh/BRepMesh_FastDiscretFace.cdl @@ -39,6 +39,7 @@ uses Boolean from Standard, DataMapOfVertexInteger from BRepMesh, DataMapOfIntegerListOfXY from BRepMesh, DataMapOfShapeReal from TopTools, + MutexForShapeProvider from TopTools, ListOfVertex from BRepMesh, ClassifierPtr from BRepMesh, Triangle from BRepMesh, @@ -54,7 +55,6 @@ uses Boolean from Standard, Triangulation from Poly, Location from TopLoc - is Create (theAngle : Real from Standard; @@ -67,7 +67,8 @@ is Add (me : mutable; theFace : Face from TopoDS; theAttrib : FaceAttribute from BRepMesh; - theMapDefle : DataMapOfShapeReal from TopTools) + theMapDefle : DataMapOfShapeReal from TopTools; + theMutexProvider : MutexForShapeProvider from TopTools) is static; @@ -116,7 +117,8 @@ is AddInShape (me: mutable; theFace : Face from TopoDS; - theDefFace: Real from Standard) + theDefFace: Real from Standard; + theMutexProvider: MutexForShapeProvider from TopTools) is static private; diff --git a/src/BRepMesh/BRepMesh_FastDiscretFace.cxx b/src/BRepMesh/BRepMesh_FastDiscretFace.cxx index 68093a6c8e..5cacdf6762 100755 --- a/src/BRepMesh/BRepMesh_FastDiscretFace.cxx +++ b/src/BRepMesh/BRepMesh_FastDiscretFace.cxx @@ -108,7 +108,8 @@ BRepMesh_FastDiscretFace::BRepMesh_FastDiscretFace void BRepMesh_FastDiscretFace::Add(const TopoDS_Face& theFace, const Handle(BRepMesh_FaceAttribute)& theAttrib, - const TopTools_DataMapOfShapeReal& theMapDefle) + const TopTools_DataMapOfShapeReal& theMapDefle, + const TopTools_MutexForShapeProvider& theMutexProvider) { #ifndef DEB_MESH try @@ -324,7 +325,7 @@ void BRepMesh_FastDiscretFace::Add(const TopoDS_Face& theFace } myStructure->ReplaceNodes(aMoveNodes); - AddInShape(face, (aDef < 0.0)? theAttrib->GetDefFace() : aDef); + AddInShape(face, (aDef < 0.0)? theAttrib->GetDefFace() : aDef, theMutexProvider); #ifndef DEB_MESH } catch(Standard_Failure) @@ -1522,12 +1523,15 @@ Standard_Real BRepMesh_FastDiscretFace::Control(const Handle(BRepAdaptor_HSurfac return Sqrt(maxdef); } +static Standard_Mutex DummyMutex; + //======================================================================= //function : AddInShape //purpose : //======================================================================= void BRepMesh_FastDiscretFace::AddInShape(const TopoDS_Face& theFace, - const Standard_Real theDefFace) + const Standard_Real theDefFace, + const TopTools_MutexForShapeProvider& theMutexProvider) { // gp_Pnt Pt; BRep_Builder B; @@ -1624,6 +1628,12 @@ void BRepMesh_FastDiscretFace::AddInShape(const TopoDS_Face& theFace, const BRepMesh_PairOfPolygon& pair = It.Value(); const Handle(Poly_PolygonOnTriangulation)& NOD1 = pair.First(); const Handle(Poly_PolygonOnTriangulation)& NOD2 = pair.Last(); + + // lock mutex to prevent parallel change of the same data + Standard_Mutex* aMutex = theMutexProvider.GetMutex(It.Key()); + Standard_Mutex::SentryNested (aMutex == NULL ? DummyMutex : *aMutex, + aMutex != NULL); + if ( NOD1 == NOD2 ) { B.UpdateEdge(TopoDS::Edge(It.Key()), NullPoly, TOld,loc); B.UpdateEdge(TopoDS::Edge(It.Key()), NOD1, T, loc); diff --git a/src/BRepMesh/BRepMesh_IncrementalMesh.cxx b/src/BRepMesh/BRepMesh_IncrementalMesh.cxx index 8c3aa81c88..50c349d92c 100755 --- a/src/BRepMesh/BRepMesh_IncrementalMesh.cxx +++ b/src/BRepMesh/BRepMesh_IncrementalMesh.cxx @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -260,6 +261,7 @@ void BRepMesh_IncrementalMesh::Update(const TopoDS_Shape& S) if (myInParallel) { #ifdef HAVE_TBB + myMesh->CreateMutexesForSubShapes(S, TopAbs_EDGE); // mesh faces in parallel threads using TBB tbb::parallel_for_each (aFaces.begin(), aFaces.end(), *myMesh.operator->()); #else @@ -267,6 +269,7 @@ void BRepMesh_IncrementalMesh::Update(const TopoDS_Shape& S) for (std::vector::iterator it(aFaces.begin()); it != aFaces.end(); it++) myMesh->Process (*it); #endif + myMesh->RemoveAllMutexes(); } else { diff --git a/src/Standard/Standard_Mutex.hxx b/src/Standard/Standard_Mutex.hxx index 0d7606075d..1411c064f6 100755 --- a/src/Standard/Standard_Mutex.hxx +++ b/src/Standard/Standard_Mutex.hxx @@ -198,6 +198,11 @@ private: //! Callback method to unlock the mutex if OCC exception or signal is raised virtual void DestroyCallback (); + //! This method should not be called (prohibited). + Standard_Mutex (const Standard_Mutex &); + //! This method should not be called (prohibited). + Standard_Mutex& operator = (const Standard_Mutex &); + private: #ifdef WNT CRITICAL_SECTION myMutex; diff --git a/src/TopTools/FILES b/src/TopTools/FILES new file mode 100644 index 0000000000..7ac5ad0685 --- /dev/null +++ b/src/TopTools/FILES @@ -0,0 +1,2 @@ +TopTools_MutexForShapeProvider.hxx +TopTools_MutexForShapeProvider.cxx \ No newline at end of file diff --git a/src/TopTools/TopTools.cdl b/src/TopTools/TopTools.cdl index d86918b166..d950c35357 100755 --- a/src/TopTools/TopTools.cdl +++ b/src/TopTools/TopTools.cdl @@ -213,7 +213,9 @@ is -- -- Package methods - -- + -- + + imported MutexForShapeProvider; Dump(Sh : Shape from TopoDS; S : in out OStream); ---Purpose: Dumps the topological structure of on the diff --git a/src/TopTools/TopTools_MutexForShapeProvider.cxx b/src/TopTools/TopTools_MutexForShapeProvider.cxx new file mode 100644 index 0000000000..aa5222bde2 --- /dev/null +++ b/src/TopTools/TopTools_MutexForShapeProvider.cxx @@ -0,0 +1,112 @@ +// Created on: 2012-06-27 +// Created by: Dmitry BOBYLEV +// Copyright (c) 2012 OPEN CASCADE SAS +// +// The content of this file is subject to the Open CASCADE Technology Public +// License Version 6.5 (the "License"). You may not use the content of this file +// except in compliance with the License. Please obtain a copy of the License +// at http://www.opencascade.org and read it completely before using this file. +// +// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its +// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. +// +// The Original Code and all software distributed under the License is +// distributed on an "AS IS" basis, without warranty of any kind, and the +// Initial Developer hereby disclaims all such warranties, including without +// limitation, any warranties of merchantability, fitness for a particular +// purpose or non-infringement. Please see the License for the specific terms +// and conditions governing the rights and limitations under the License. + +#include + +#include + +// macro to compare two types of shapes +#define SAMETYPE(x,y) ((x) == (y)) +#define LESSCOMPLEX(x,y) ((x) > (y)) + +//======================================================================= +//function : TopTools_MutexForShapeProvider +//purpose : +//======================================================================= +TopTools_MutexForShapeProvider::TopTools_MutexForShapeProvider() +{ +} + + +//======================================================================= +//function : ~TopTools_MutexForShapeProvider +//purpose : +//======================================================================= +TopTools_MutexForShapeProvider::~TopTools_MutexForShapeProvider() +{ + RemoveAllMutexes(); +} + +//======================================================================= +//function : CreateMutexesForSubShapes +//purpose : +//======================================================================= +void TopTools_MutexForShapeProvider::CreateMutexesForSubShapes(const TopoDS_Shape& theShape, + const TopAbs_ShapeEnum theType) +{ + if (LESSCOMPLEX(theShape.ShapeType(), theType)) + return; + + for(TopoDS_Iterator anIt(theShape); anIt.More(); anIt.Next()) + { + const TopoDS_Shape& aShape = anIt.Value(); + if (LESSCOMPLEX(theType, aShape.ShapeType())) + { + CreateMutexesForSubShapes(aShape, theType); + } + else if (SAMETYPE(theType, aShape.ShapeType())) + { + CreateMutexForShape(aShape); + } + } +} + +//======================================================================= +//function : CreateMutexForShape +//purpose : +//======================================================================= +void TopTools_MutexForShapeProvider::CreateMutexForShape(const TopoDS_Shape& theShape) +{ + if (!myMap.IsBound(theShape)) + { + Standard_Mutex* aMutex = new Standard_Mutex(); + myMap.Bind(theShape, aMutex); + } +} + +//======================================================================= +//function : CreateMutexForShape +//purpose : +//======================================================================= +Standard_Mutex* TopTools_MutexForShapeProvider::GetMutex(const TopoDS_Shape& theShape) const +{ + if (myMap.IsBound(theShape)) + { + Standard_Mutex* aMutex = myMap.Find(theShape); + return aMutex; + } + else + { + return NULL; + } +} + +//======================================================================= +//function : RemoveAllMutexes +//purpose : +//======================================================================= +void TopTools_MutexForShapeProvider::RemoveAllMutexes() +{ + for (NCollection_DataMap::Iterator anIter; + anIter.More(); anIter.Next()) + { + delete anIter.Value(); + } + myMap.Clear(); +} diff --git a/src/TopTools/TopTools_MutexForShapeProvider.hxx b/src/TopTools/TopTools_MutexForShapeProvider.hxx new file mode 100644 index 0000000000..409116b99d --- /dev/null +++ b/src/TopTools/TopTools_MutexForShapeProvider.hxx @@ -0,0 +1,66 @@ +// Created on: 2012-06-27 +// Created by: Dmitry BOBYLEV +// Copyright (c) 2012 OPEN CASCADE SAS +// +// The content of this file is subject to the Open CASCADE Technology Public +// License Version 6.5 (the "License"). You may not use the content of this file +// except in compliance with the License. Please obtain a copy of the License +// at http://www.opencascade.org and read it completely before using this file. +// +// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its +// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. +// +// The Original Code and all software distributed under the License is +// distributed on an "AS IS" basis, without warranty of any kind, and the +// Initial Developer hereby disclaims all such warranties, including without +// limitation, any warranties of merchantability, fitness for a particular +// purpose or non-infringement. Please see the License for the specific terms +// and conditions governing the rights and limitations under the License. + + +#ifndef _TopTools_MutexForShapeProvider_HeaderFile +#define _TopTools_MutexForShapeProvider_HeaderFile + +#include +#include +#include +#include +#include + + +//! Class TopTools_MutexForShapeProvider +//! This class is used to create and store mutexes associated with shapes. +class TopTools_MutexForShapeProvider +{ +public: + //! Constructor + Standard_EXPORT TopTools_MutexForShapeProvider(); + + //! Destructor + Standard_EXPORT ~TopTools_MutexForShapeProvider(); + + //! Creates and associates mutexes with each sub-shape of type theType in theShape. + Standard_EXPORT void CreateMutexesForSubShapes(const TopoDS_Shape& theShape, const TopAbs_ShapeEnum theType); + + //! Creates and associates mutex with theShape + Standard_EXPORT void CreateMutexForShape(const TopoDS_Shape& theShape); + + //! Returns pointer to mutex associated with theShape. + //! In case when mutex not found returns NULL. + Standard_EXPORT Standard_Mutex* GetMutex(const TopoDS_Shape& theShape) const; + + //! Removes all mutexes + Standard_EXPORT void RemoveAllMutexes(); + +private: + //! This method should not be called (prohibited). + TopTools_MutexForShapeProvider (const TopTools_MutexForShapeProvider &); + //! This method should not be called (prohibited). + TopTools_MutexForShapeProvider & operator = (const TopTools_MutexForShapeProvider &); + + + NCollection_DataMap myMap; + +}; + +#endif \ No newline at end of file