0022850: Not stable fix 22735
authordbv <dbv@opencascade.com>
Fri, 6 Jul 2012 12:08:21 +0000 (16:08 +0400)
committerdbv <dbv@opencascade.com>
Fri, 6 Jul 2012 12:08:21 +0000 (16:08 +0400)
Class TopTools_MutexForShapeProvider has been created
Class contain methods:
TopTools_MutexForShapeProvider::CreateMutexesForSubShapes - Creates and associates mutexes with each sub-shape of type theType in theShape.
TopTools_MutexForShapeProvider::CreateMutexForShape - Creates and associates mutex with theShape
TopTools_MutexForShapeProvider::GetMutex - Returns pointer to mutex associated with theShape. In case when mutex not found returns NULL.

Added method RemoveAllMutexes to TopTools_MutexForShapeProvider
Assign operator in MutexProvider, constructor and operator and assign operator in Standard_Mutex now private
Replaced TopExp_Explorer with TopoDS_Iterator to avoid cyclic dependence

src/BRepMesh/BRepMesh_FastDiscret.cdl
src/BRepMesh/BRepMesh_FastDiscret.cxx
src/BRepMesh/BRepMesh_FastDiscretFace.cdl
src/BRepMesh/BRepMesh_FastDiscretFace.cxx
src/BRepMesh/BRepMesh_IncrementalMesh.cxx
src/Standard/Standard_Mutex.hxx
src/TopTools/FILES [new file with mode: 0644]
src/TopTools/TopTools.cdl
src/TopTools/TopTools_MutexForShapeProvider.cxx [new file with mode: 0644]
src/TopTools/TopTools_MutexForShapeProvider.hxx [new file with mode: 0644]

index 183a881..7affa55 100755 (executable)
@@ -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;
index 2d8dcde..1d4d927 100755 (executable)
@@ -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<TopoDS_Face>::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
index 3930b32..53e2c69 100755 (executable)
@@ -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;
 
 
index 68093a6..5cacdf6 100755 (executable)
@@ -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);
index 8c3aa81..50c349d 100755 (executable)
@@ -40,6 +40,7 @@
 #include <TopExp_Explorer.hxx>
 #include <TopAbs.hxx>
 #include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopTools_MutexForShapeProvider.hxx>
 #include <TColgp_Array1OfPnt.hxx>
 #include <TColStd_Array1OfReal.hxx>
 #include <TopoDS_Shape.hxx>
@@ -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<TopoDS_Face>::iterator it(aFaces.begin()); it != aFaces.end(); it++)
       myMesh->Process (*it);
   #endif
+    myMesh->RemoveAllMutexes();
   }
   else
   {
index 0d76060..1411c06 100755 (executable)
@@ -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 (file)
index 0000000..7ac5ad0
--- /dev/null
@@ -0,0 +1,2 @@
+TopTools_MutexForShapeProvider.hxx
+TopTools_MutexForShapeProvider.cxx
\ No newline at end of file
index d86918b..d950c35 100755 (executable)
@@ -213,7 +213,9 @@ is
        
     --
     --     Package methods
-    --     
+    --   
+
+    imported MutexForShapeProvider;
     
     Dump(Sh : Shape from TopoDS; S : in out OStream);
          ---Purpose: Dumps the topological structure  of <Sh>  on the
diff --git a/src/TopTools/TopTools_MutexForShapeProvider.cxx b/src/TopTools/TopTools_MutexForShapeProvider.cxx
new file mode 100644 (file)
index 0000000..aa5222b
--- /dev/null
@@ -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 <TopTools_MutexForShapeProvider.hxx>
+
+#include <TopoDS_Iterator.hxx>
+
+// 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<TopoDS_Shape, Standard_Mutex *, TopTools_ShapeMapHasher>::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 (file)
index 0000000..409116b
--- /dev/null
@@ -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 <NCollection_DataMap.hxx>
+#include <Standard_Mutex.hxx>
+#include <TopAbs_ShapeEnum.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TopTools_ShapeMapHasher.hxx>
+
+
+//! 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<TopoDS_Shape, Standard_Mutex *, TopTools_ShapeMapHasher> myMap;
+
+};
+
+#endif
\ No newline at end of file