]> OCCT Git - occt-copy.git/commitdiff
0032539: Parallelize distance
authorasuraven <andrey.suravenkov@opencascade.com>
Wed, 25 Aug 2021 18:19:00 +0000 (21:19 +0300)
committerasuraven <andrey.suravenkov@opencascade.com>
Mon, 30 Aug 2021 13:00:58 +0000 (16:00 +0300)
src/BRepExtrema/BRepExtrema_DistShapeShape.cxx
src/BRepExtrema/BRepExtrema_DistShapeShape.hxx

index 1e808bc5917441bc05cf7872df9aea3ec58a47b4..aec844ff0817621d240182fcbaedaf6230e7f6f2 100644 (file)
@@ -105,7 +105,167 @@ namespace
     return (theLeft.Distance < theRight.Distance);
   }
 }
+//=======================================================================
+//struct   : VertexTask
+//purpose  : 
+//=======================================================================
+struct VertexTask
+{
+  VertexTask(Standard_Integer theFirtsIndex,
+             Standard_Integer theLastIndex,
+             BRepExtrema_SeqOfSolution* theSolutionsShape1,
+             BRepExtrema_SeqOfSolution* theSolutionsShape2,
+             const TopTools_IndexedMapOfShape* theMap1,
+             const TopTools_IndexedMapOfShape* theMap2,
+             const Bnd_SeqOfBox* theLBox1,
+             const Bnd_SeqOfBox* theLBox2,
+             const Message_ProgressRange theRange,
+             Standard_Boolean* theIsBreak,
+             Standard_Real* theDistRef,
+             Standard_Real theEps,
+             Handle(Standard_HMutex) theMutex)
+    : myFirtsIndex(theFirtsIndex),
+    myLastIndex(theLastIndex),    
+    mySolutionsShape1(theSolutionsShape1),
+    mySolutionsShape2(theSolutionsShape2),
+    myMap1(theMap1),
+    myMap2(theMap2),
+    myLBox1(theLBox1),
+    myLBox2(theLBox2),
+    myRange(theRange),
+    myIsBreak(theIsBreak),
+    myDistRef(theDistRef),
+    myEps(theEps),
+    myMutex(theMutex)
+  {
+  }
+
+  VertexTask()
+    : myFirtsIndex(0),
+    myLastIndex(0), 
+    mySolutionsShape1(NULL),
+    mySolutionsShape2(NULL),
+    myMap1(NULL),
+    myMap2(NULL),
+    myLBox1(NULL),
+    myLBox2(NULL),
+    myIsBreak(NULL),
+    myDistRef(NULL),
+    myEps(Precision::Confusion()),
+    myMutex(NULL)
+  {
+  }
+
+  VertexTask& VertexTask::operator =(const VertexTask& theCopy)
+  {
+    myFirtsIndex = theCopy.myFirtsIndex;
+    myLastIndex = theCopy.myLastIndex;
+    mySolutionsShape1 = theCopy.mySolutionsShape1;
+    mySolutionsShape2 = theCopy.mySolutionsShape2;
+    myMap1 = theCopy.myMap1;
+    myMap2 = theCopy.myMap2;
+    myLBox1 = theCopy.myLBox1;
+    myLBox2 = theCopy.myLBox2;
+    myRange = theCopy.myRange;
+    myIsBreak = theCopy.myIsBreak;
+    myDistRef = theCopy.myDistRef;
+    myEps = theCopy.myEps;
+    myMutex = theCopy.myMutex;
+    return *this;
+  }
 
+  Standard_Integer myFirtsIndex;
+  Standard_Integer myLastIndex;
+  BRepExtrema_SeqOfSolution* mySolutionsShape1;
+  BRepExtrema_SeqOfSolution* mySolutionsShape2;
+  const TopTools_IndexedMapOfShape* myMap1;
+  const TopTools_IndexedMapOfShape* myMap2;
+  const Bnd_SeqOfBox* myLBox1;
+  const Bnd_SeqOfBox* myLBox2;
+  Message_ProgressRange myRange;
+  Standard_Boolean* myIsBreak;
+  Standard_Real* myDistRef;
+  Standard_Real myEps;
+  Handle(Standard_HMutex) myMutex;
+};
+
+//=======================================================================
+//struct   : VertexFunctor
+//purpose  : 
+//=======================================================================
+struct VertexFunctor
+{
+  void operator() (VertexTask& theTask) const
+  {
+    const Standard_Integer aCount1 = theTask.myMap1->Extent();
+    const Standard_Integer aCount2 = theTask.myMap2->Extent();
+
+    Message_ProgressScope aScope(theTask.myRange, NULL, aCount1);
+
+    for (Standard_Integer anIdx1 = theTask.myFirtsIndex; anIdx1 <= theTask.myLastIndex; ++anIdx1)
+    {
+      if (!aScope.More())
+      {
+        Standard_Atomic_CompareAndSwap((int*) *theTask.myIsBreak, Standard_False, Standard_True);
+      }
+      aScope.Next();
+      if (*theTask.myIsBreak)
+      {
+        break;
+      }
+
+      for (Standard_Integer anIdx2 = 1; anIdx2 <= aCount2; ++anIdx2)
+      {
+        const Bnd_Box& aBox1 = theTask.myLBox1->Value(anIdx1);
+        const Bnd_Box& aBox2 = theTask.myLBox2->Value(anIdx2);
+        if (aBox1.IsVoid()
+            || aBox2.IsVoid())
+        {
+          continue;
+        }
+        const TopoDS_Shape& aShape1 = theTask.myMap1->FindKey(anIdx1);
+        const TopoDS_Shape& aShape2 = theTask.myMap2->FindKey(anIdx2);
+
+        Standard_Real aDistRef(0);
+        {
+          Standard_Mutex::Sentry aLock(theTask.myMutex.get());
+          aDistRef = *theTask.myDistRef;
+        }
+        BRepExtrema_DistanceSS aDistTool(aShape1, aShape2, aBox1, aBox2, aDistRef, theTask.myEps);
+        if (aDistTool.IsDone())
+        {
+          Standard_Mutex::Sentry aLock(theTask.myMutex.get());
+          if (aDistTool.DistValue() < *theTask.myDistRef - theTask.myEps)
+          {
+            theTask.mySolutionsShape1->Clear();
+            theTask.mySolutionsShape2->Clear();
+
+            BRepExtrema_SeqOfSolution aSeq1 = aDistTool.Seq1Value();
+            BRepExtrema_SeqOfSolution aSeq2 = aDistTool.Seq2Value();
+
+            theTask.mySolutionsShape1->Append(aSeq1);
+            theTask.mySolutionsShape2->Append(aSeq2);
+
+            *theTask.myDistRef = aDistTool.DistValue();
+          }
+          else if (fabs(aDistTool.DistValue() - *theTask.myDistRef) < theTask.myEps)
+          {
+            BRepExtrema_SeqOfSolution aSeq1 = aDistTool.Seq1Value();
+            BRepExtrema_SeqOfSolution aSeq2 = aDistTool.Seq2Value();
+
+            theTask.mySolutionsShape1->Append(aSeq1);
+            theTask.mySolutionsShape2->Append(aSeq2);
+
+            if (*theTask.myDistRef > aDistTool.DistValue())
+            {
+              *theTask.myDistRef = aDistTool.DistValue();
+            }
+          }
+        }
+      }
+    }
+  }
+};
 //=======================================================================
 //function : DistanceMapMap
 //purpose  : 
@@ -117,64 +277,256 @@ void BRepExtrema_DistShapeShape::DistanceVertVert(const TopTools_IndexedMapOfSha
                                                   const Bnd_SeqOfBox& theLBox2,
                                                   const Message_ProgressRange& theRange)
 {
-  NCollection_Vector<BRepExtrema_CheckPair> aPairList;
   const Standard_Integer aCount1 = theMap1.Extent();
   const Standard_Integer aCount2 = theMap2.Extent();
 
-  Message_ProgressScope aScope(theRange, NULL, aCount1);
+  if (myMutex.IsNull())
+  {
+    Message_ProgressScope aScope(theRange, NULL, aCount1);
 
-  for (Standard_Integer anIdx1 = 1; anIdx1 <= aCount1; ++anIdx1)
+    for (Standard_Integer anIdx1 = 1; anIdx1 <= aCount1; ++anIdx1)
+    {
+      aScope.Next();
+      if (!aScope.More())
+      {
+        throw StdFail_NotDone();
+      }
+      for (Standard_Integer anIdx2 = 1; anIdx2 <= aCount2; ++anIdx2)
+      {
+        const Bnd_Box& aBox1 = theLBox1.Value(anIdx1);
+        const Bnd_Box& aBox2 = theLBox2.Value(anIdx2);
+        if (aBox1.IsVoid()
+            || aBox2.IsVoid())
+        {
+          continue;
+        }
+        const TopoDS_Shape& aShape1 = theMap1.FindKey(anIdx1);
+        const TopoDS_Shape& aShape2 = theMap2.FindKey(anIdx2);
+
+        BRepExtrema_DistanceSS aDistTool(aShape1, aShape2, aBox1, aBox2, myDistRef, myEps);
+        if (aDistTool.IsDone())
+        {
+          if (aDistTool.DistValue() < myDistRef - myEps)
+          {
+            mySolutionsShape1.Clear();
+            mySolutionsShape2.Clear();
+
+            BRepExtrema_SeqOfSolution aSeq1 = aDistTool.Seq1Value();
+            BRepExtrema_SeqOfSolution aSeq2 = aDistTool.Seq2Value();
+
+            mySolutionsShape1.Append(aSeq1);
+            mySolutionsShape2.Append(aSeq2);
+
+            myDistRef = aDistTool.DistValue();
+          }
+          else if (fabs(aDistTool.DistValue() - myDistRef) < myEps)
+          {
+            BRepExtrema_SeqOfSolution aSeq1 = aDistTool.Seq1Value();
+            BRepExtrema_SeqOfSolution aSeq2 = aDistTool.Seq2Value();
+
+            mySolutionsShape1.Append(aSeq1);
+            mySolutionsShape2.Append(aSeq2);
+
+            if (myDistRef > aDistTool.DistValue())
+            {
+              myDistRef = aDistTool.DistValue();
+            }
+          }
+        }
+      }
+    }
+  }
+  else
   {
-    aScope.Next();
-    if (!aScope.More())
+    const Standard_Integer aMinTaskSize = 10;
+    const Handle(OSD_ThreadPool)& aThreadPool = OSD_ThreadPool::DefaultPool();
+    const Standard_Integer aNbThreads = aThreadPool->NbThreads();
+    Standard_Integer aNbTasks = aNbThreads * 10;
+    Standard_Integer aTaskSize = (Standard_Integer) Ceiling((double) aCount1 / aNbTasks);
+    if (aTaskSize < aMinTaskSize)
+    {
+      aTaskSize = aMinTaskSize;
+      aNbTasks = (Standard_Integer) Ceiling((double) aCount1 / aTaskSize);
+    }
+
+    Standard_Integer aFirstIndex(1);
+    NCollection_Array1<VertexTask> aTaskArray(0, aNbTasks - 1);
+    Message_ProgressScope aDistScope(theRange, NULL, aNbTasks);
+    for (Standard_Integer anI = 0; anI < aTaskArray.Size(); ++anI)
+    {
+      VertexTask aTask(aFirstIndex, aFirstIndex + aTaskSize,
+                       &mySolutionsShape1, &mySolutionsShape2,
+                       &theMap1, &theMap2, &theLBox1, &theLBox2,
+                       aDistScope.Next(), &myIsBreak, &myDistRef,
+                       myEps, myMutex);
+      aTaskArray.SetValue(anI, aTask);
+    }
+    OSD_Parallel::ForEach(aTaskArray.begin(), aTaskArray.end(), VertexFunctor(), Standard_False);
+
+    if (myIsBreak)
     {
       throw StdFail_NotDone();
     }
-    for (Standard_Integer anIdx2 = 1; anIdx2 <= aCount2; ++anIdx2)
+  }
+}
+
+
+//=======================================================================
+//struct   : DistanceTask
+//purpose  : 
+//=======================================================================
+struct DistanceTask
+{
+  DistanceTask(const NCollection_Array1<BRepExtrema_CheckPair>* theArray,
+               BRepExtrema_SeqOfSolution* theSolutionsShape1,
+               BRepExtrema_SeqOfSolution* theSolutionsShape2,
+               const TopTools_IndexedMapOfShape* theMap1,
+               const TopTools_IndexedMapOfShape* theMap2,
+               const Bnd_SeqOfBox* theLBox1,
+               const Bnd_SeqOfBox* theLBox2,
+               const Message_ProgressRange theRange,
+               Standard_Boolean* theIsBreak,
+               Standard_Boolean* theIsDone,
+               Standard_Real* theDistRef,
+               Standard_Real theEps,
+               Handle(Standard_HMutex) theMutex)
+    : myArray(theArray),
+    mySolutionsShape1(theSolutionsShape1),
+    mySolutionsShape2(theSolutionsShape2),
+    myMap1(theMap1),
+    myMap2(theMap2),
+    myLBox1(theLBox1),
+    myLBox2(theLBox2),
+    myRange(theRange),
+    myIsBreak(theIsBreak),
+    myIsDone(theIsDone),
+    myDistRef(theDistRef),
+    myEps(theEps),
+    myMutex(theMutex)
+  {
+  }
+
+  DistanceTask()
+    : myArray(NULL),
+    mySolutionsShape1(NULL),
+    mySolutionsShape2(NULL),
+    myMap1(NULL),
+    myMap2(NULL),
+    myLBox1(NULL),
+    myLBox2(NULL),
+    myIsBreak(NULL),
+    myIsDone(NULL),
+    myDistRef(NULL),
+    myEps(Precision::Confusion()),
+    myMutex(NULL)
+  {
+  }
+
+  DistanceTask& DistanceTask::operator =(const DistanceTask& theCopy)
+  {
+    myArray = theCopy.myArray;
+    mySolutionsShape1 = theCopy.mySolutionsShape1;
+    mySolutionsShape2 = theCopy.mySolutionsShape2;
+    myMap1 = theCopy.myMap1;
+    myMap2 = theCopy.myMap2;
+    myLBox1 = theCopy.myLBox1;
+    myLBox2 = theCopy.myLBox2;
+    myRange = theCopy.myRange;
+    myIsBreak = theCopy.myIsBreak;
+    myIsDone = theCopy.myIsDone;
+    myDistRef = theCopy.myDistRef;
+    myEps = theCopy.myEps;
+    myMutex = theCopy.myMutex;
+    return *this;
+  }
+
+  BRepExtrema_SeqOfSolution* mySolutionsShape1;
+  BRepExtrema_SeqOfSolution* mySolutionsShape2;
+  const NCollection_Array1<BRepExtrema_CheckPair>* myArray;
+  const TopTools_IndexedMapOfShape* myMap1;
+  const TopTools_IndexedMapOfShape* myMap2;
+  const Bnd_SeqOfBox* myLBox1;
+  const Bnd_SeqOfBox* myLBox2;
+  Message_ProgressRange myRange;
+  Standard_Boolean* myIsBreak;
+  Standard_Boolean* myIsDone;
+  Standard_Real* myDistRef;
+  Standard_Real myEps;
+  Handle(Standard_HMutex) myMutex;
+};
+
+//=======================================================================
+//struct   : DistanceFunctor
+//purpose  : 
+//=======================================================================
+struct DistanceFunctor
+{
+  void operator() (DistanceTask& theTask) const
+  {
+    Message_ProgressScope aDistScope(theTask.myRange, NULL, theTask.myArray->Size());
+    Standard_Real& anEps = theTask.myEps;
+    for (Standard_Integer i = 0; i < theTask.myArray->Size(); i++)
     {
-      const Bnd_Box& aBox1 = theLBox1.Value(anIdx1);
-      const Bnd_Box& aBox2 = theLBox2.Value(anIdx2);
-      if (aBox1.IsVoid()
-          || aBox2.IsVoid())
+      if (!aDistScope.More())
       {
-        continue;
+        Standard_Atomic_CompareAndSwap((int*) *theTask.myIsBreak, Standard_False, Standard_True);
+      }
+      aDistScope.Next();
+      if (*theTask.myIsBreak || *theTask.myIsDone)
+      {
+        break;
       }
-      const TopoDS_Shape& aShape1 = theMap1.FindKey(anIdx1);
-      const TopoDS_Shape& aShape2 = theMap2.FindKey(anIdx1);
 
-      BRepExtrema_DistanceSS aDistTool(aShape1, aShape2, aBox1, aBox2, myDistRef, myEps);
+      const BRepExtrema_CheckPair& aPair = theTask.myArray->Value(i);
+      {
+        Standard_Mutex::Sentry aLock(theTask.myMutex.get());
+        if (aPair.Distance > *theTask.myDistRef + anEps)
+        {
+          *theTask.myIsDone = Standard_True;
+          break; // early search termination
+        }
+      }
+
+      const Bnd_Box& aBox1 = theTask.myLBox1->Value(aPair.Index1);
+      const Bnd_Box& aBox2 = theTask.myLBox2->Value(aPair.Index2);
+
+      const TopoDS_Shape& aShape1 = theTask.myMap1->FindKey(aPair.Index1);
+      const TopoDS_Shape& aShape2 = theTask.myMap2->FindKey(aPair.Index2);
+
+      BRepExtrema_DistanceSS aDistTool(aShape1, aShape2, aBox1, aBox2, *theTask.myDistRef, anEps);
       if (aDistTool.IsDone())
       {
-        if (aDistTool.DistValue() < myDistRef - myEps)
+        Standard_Mutex::Sentry aLock(theTask.myMutex.get());
+        if (aDistTool.DistValue() < *theTask.myDistRef - anEps)
         {
-          mySolutionsShape1.Clear();
-          mySolutionsShape2.Clear();
+          theTask.mySolutionsShape1->Clear();
+          theTask.mySolutionsShape2->Clear();
 
           BRepExtrema_SeqOfSolution aSeq1 = aDistTool.Seq1Value();
           BRepExtrema_SeqOfSolution aSeq2 = aDistTool.Seq2Value();
 
-          mySolutionsShape1.Append(aSeq1);
-          mySolutionsShape2.Append(aSeq2);
+          theTask.mySolutionsShape1->Append(aSeq1);
+          theTask.mySolutionsShape2->Append(aSeq2);
 
-          myDistRef = aDistTool.DistValue();
+          *theTask.myDistRef = aDistTool.DistValue();
         }
-        else if (fabs(aDistTool.DistValue() - myDistRef) < myEps)
+        else if (fabs(aDistTool.DistValue() - *theTask.myDistRef) < anEps)
         {
           BRepExtrema_SeqOfSolution aSeq1 = aDistTool.Seq1Value();
           BRepExtrema_SeqOfSolution aSeq2 = aDistTool.Seq2Value();
 
-          mySolutionsShape1.Append(aSeq1);
-          mySolutionsShape2.Append(aSeq2);
+          theTask.mySolutionsShape1->Append(aSeq1);
+          theTask.mySolutionsShape2->Append(aSeq2);
 
-          if (myDistRef > aDistTool.DistValue())
+          if (*theTask.myDistRef > aDistTool.DistValue())
           {
-            myDistRef = aDistTool.DistValue();
+            *theTask.myDistRef = aDistTool.DistValue();
           }
         }
       }
     }
   }
-}
+};
 
 //=======================================================================
 //function : DistanceMapMap
@@ -222,55 +574,110 @@ void BRepExtrema_DistShapeShape::DistanceMapMap (const TopTools_IndexedMapOfShap
 
   std::stable_sort(aPairList.begin(), aPairList.end(), BRepExtrema_CheckPair_Comparator);
   Message_ProgressRange aDistRange(aTwinScope.Next());
-  Message_ProgressScope aDistScope(aDistRange, NULL, aPairList.Size());
-  for (NCollection_Vector<BRepExtrema_CheckPair>::Iterator aPairIter (aPairList);
-       aPairIter.More(); aPairIter.Next())
+  if (myMutex.IsNull())
   {
-    aDistScope.Next();
-    if (!aDistScope.More())
+    Message_ProgressScope aDistScope(aDistRange, NULL, aPairList.Size());
+    for (NCollection_Vector<BRepExtrema_CheckPair>::Iterator aPairIter(aPairList);
+         aPairIter.More(); aPairIter.Next())
     {
-      throw StdFail_NotDone();
-    }
-    const BRepExtrema_CheckPair& aPair = aPairIter.Value();
-    if (aPair.Distance > myDistRef + myEps)
-    {
-      break; // early search termination
-    }
+      aDistScope.Next();
+      if (!aDistScope.More())
+      {
+        throw StdFail_NotDone();
+      }
+      const BRepExtrema_CheckPair& aPair = aPairIter.Value();
+      if (aPair.Distance > myDistRef + myEps)
+      {
+        break; // early search termination
+      }
 
-    const Bnd_Box& aBox1 = theLBox1.Value (aPair.Index1);
-    const Bnd_Box& aBox2 = theLBox2.Value (aPair.Index2);
+      const Bnd_Box& aBox1 = theLBox1.Value(aPair.Index1);
+      const Bnd_Box& aBox2 = theLBox2.Value(aPair.Index2);
 
-    const TopoDS_Shape& aShape1 = theMap1 (aPair.Index1);
-    const TopoDS_Shape& aShape2 = theMap2 (aPair.Index2);
+      const TopoDS_Shape& aShape1 = theMap1(aPair.Index1);
+      const TopoDS_Shape& aShape2 = theMap2(aPair.Index2);
 
-    BRepExtrema_DistanceSS aDistTool (aShape1, aShape2, aBox1, aBox2, myDistRef, myEps);
-    if (aDistTool.IsDone())
-    {
-      if (aDistTool.DistValue() < myDistRef - myEps)
+      BRepExtrema_DistanceSS aDistTool(aShape1, aShape2, aBox1, aBox2, myDistRef, myEps);
+      if (aDistTool.IsDone())
       {
-        mySolutionsShape1.Clear();
-        mySolutionsShape2.Clear();
+        if (aDistTool.DistValue() < myDistRef - myEps)
+        {
+          mySolutionsShape1.Clear();
+          mySolutionsShape2.Clear();
+
+          BRepExtrema_SeqOfSolution aSeq1 = aDistTool.Seq1Value();
+          BRepExtrema_SeqOfSolution aSeq2 = aDistTool.Seq2Value();
+
+          mySolutionsShape1.Append(aSeq1);
+          mySolutionsShape2.Append(aSeq2);
 
-        BRepExtrema_SeqOfSolution aSeq1 = aDistTool.Seq1Value();
-        BRepExtrema_SeqOfSolution aSeq2 = aDistTool.Seq2Value();
+          myDistRef = aDistTool.DistValue();
+        }
+        else if (fabs(aDistTool.DistValue() - myDistRef) < myEps)
+        {
+          BRepExtrema_SeqOfSolution aSeq1 = aDistTool.Seq1Value();
+          BRepExtrema_SeqOfSolution aSeq2 = aDistTool.Seq2Value();
 
-        mySolutionsShape1.Append (aSeq1);
-        mySolutionsShape2.Append (aSeq2);
+          mySolutionsShape1.Append(aSeq1);
+          mySolutionsShape2.Append(aSeq2);
 
-        myDistRef = aDistTool.DistValue();
+          if (myDistRef > aDistTool.DistValue())
+          {
+            myDistRef = aDistTool.DistValue();
+          }
+        }
       }
-      else if (fabs (aDistTool.DistValue() - myDistRef) < myEps)
+    }
+  }
+  else
+  {
+    const Standard_Integer aMapSize = aPairList.Size();
+    if (aMapSize)
+    {
+      const Standard_Integer aMinTaskSize = 2;
+      const Handle(OSD_ThreadPool)& aThreadPool = OSD_ThreadPool::DefaultPool();
+      const Standard_Integer aNbThreads = aThreadPool->NbThreads();
+      Standard_Integer aNbTasks = aNbThreads * 10;
+      Standard_Integer aTaskSize = (Standard_Integer) Ceiling((double) aMapSize / aNbTasks);
+      if (aTaskSize < aMinTaskSize)
       {
-        BRepExtrema_SeqOfSolution aSeq1 = aDistTool.Seq1Value();
-        BRepExtrema_SeqOfSolution aSeq2 = aDistTool.Seq2Value();
-
-        mySolutionsShape1.Append (aSeq1);
-        mySolutionsShape2.Append (aSeq2);
+        aTaskSize = aMinTaskSize;
+        aNbTasks = (Standard_Integer) Ceiling((double) aMapSize / aTaskSize);
+      }
 
-        if (myDistRef > aDistTool.DistValue())
+      NCollection_Array1< NCollection_Array1<BRepExtrema_CheckPair> > anArrayOfArray(0, aNbTasks - 1);
+      for (Standard_Integer anI = 0; anI < aMapSize; ++anI)
+      {
+        Standard_Integer aVectIndex = anI / aTaskSize;
+        Standard_Integer aShapeIndex = anI % aTaskSize;
+        if (aShapeIndex == 0)
         {
-          myDistRef = aDistTool.DistValue();
+          Standard_Integer aVectorSize = aTaskSize;
+          Standard_Integer aTailSize = aMapSize - aVectIndex * aTaskSize;
+          if (aTailSize < aTaskSize)
+          {
+            aVectorSize = aTailSize;
+          }
+          anArrayOfArray[aVectIndex].Resize(0, aVectorSize - 1, Standard_False);
         }
+        anArrayOfArray[aVectIndex][aShapeIndex] = aPairList(anI);
+      }
+
+      NCollection_Array1<DistanceTask> aTaskArray(0, aNbTasks - 1);
+      Message_ProgressScope aDistScope(aDistRange, NULL, aNbTasks);
+      for (Standard_Integer anI = 0; anI < aTaskArray.Size(); ++anI)
+      {
+        DistanceTask aTask(&anArrayOfArray[anI], &mySolutionsShape1, &mySolutionsShape2,
+                           &theMap1, &theMap2, &theLBox1, &theLBox2, aDistScope.Next(),
+                           &myIsBreak, &myIsDone, &myDistRef, myEps, myMutex);
+        aTaskArray.SetValue(anI, aTask);
+      }
+
+      OSD_Parallel::ForEach(aTaskArray.begin(), aTaskArray.end(), DistanceFunctor(), Standard_False);
+
+      if (myIsBreak)
+      {
+        throw StdFail_NotDone();
       }
     }
   }
@@ -290,7 +697,8 @@ BRepExtrema_DistShapeShape::BRepExtrema_DistShapeShape()
   myIsInitS2 (Standard_False),
   myFlag (Extrema_ExtFlag_MINMAX),
   myAlgo (Extrema_ExtAlgo_Grad),
-  myIsBreak(Standard_False)
+  myIsBreak(Standard_False),
+  myMutex(NULL)
 {
   //
 }
@@ -313,7 +721,8 @@ BRepExtrema_DistShapeShape::BRepExtrema_DistShapeShape(const TopoDS_Shape& Shape
   myIsInitS2 (Standard_False),
   myFlag (F),
   myAlgo (A),
-  myIsBreak(Standard_False)
+  myIsBreak(Standard_False),
+  myMutex(NULL)
 {
   LoadS1(Shape1);
   LoadS2(Shape2);
@@ -340,7 +749,8 @@ BRepExtrema_DistShapeShape::BRepExtrema_DistShapeShape(const TopoDS_Shape& Shape
   myIsInitS2 (Standard_False),
   myFlag (F),
   myAlgo (A),
-  myIsBreak(Standard_False)
+  myIsBreak(Standard_False),
+  myMutex(NULL)
 {
   LoadS1(Shape1);
   LoadS2(Shape2);
@@ -471,11 +881,10 @@ struct TreatmentFunctor
     {
       if (!aScope.More())
       {
-        Standard_Atomic_CompareAndSwap((int*) theTask.myIsBreak, Standard_False, Standard_True);
+        Standard_Atomic_CompareAndSwap((int*) *theTask.myIsBreak, Standard_False, Standard_True);
       }
       Message_ProgressRange aRange = aScope.Next();
-
-      if (!theTask.myIsBreak)
+      if (*theTask.myIsBreak || *theTask.myIsDone)
       {
         break;
       }
@@ -485,8 +894,8 @@ struct TreatmentFunctor
       aClassifier.Perform(aPnt, aTolerance);
       if (aClassifier.State() == TopAbs_IN)
       {
-        Standard_Atomic_CompareAndSwap((int*) theTask.myInnerSol, Standard_False, Standard_True);
-        Standard_Atomic_CompareAndSwap((int*) theTask.myIsDone, Standard_False, Standard_True);
+        Standard_Atomic_CompareAndSwap((int*) *theTask.myInnerSol, Standard_False, Standard_True);
+        Standard_Atomic_CompareAndSwap((int*) *theTask.myIsDone, Standard_False, Standard_True);
         BRepExtrema_SolutionElem aSolElem(0, aPnt, BRepExtrema_IsVertex, aVertex);
         theTask.mySolutionsShape.Append(aSolElem);
         break;
@@ -534,10 +943,10 @@ void BRepExtrema_DistShapeShape::SolidTreatmentMulty(const TopoDS_Shape& theShap
   }
 
   NCollection_Array1<TreatmentTask> aTaskArray(0, aNbTasks - 1);
-  Message_ProgressScope aRange(theRange, "Solid treatment", aNbTasks);
+  Message_ProgressScope aScope(theRange, "Solid treatment", aNbTasks);
   for (Standard_Integer anI = 0; anI < aTaskArray.Size(); ++anI)
   {
-    TreatmentTask aTask(&theShape, &anArrayOfArray[anI], aRange.Next(), &myIsBreak, &myInnerSol, &myIsDone);
+    TreatmentTask aTask(&theShape, &anArrayOfArray[anI], aScope.Next(), &myIsBreak, &myInnerSol, &myIsDone);
     aTaskArray.SetValue(anI, aTask);
   }
 
@@ -551,13 +960,13 @@ void BRepExtrema_DistShapeShape::SolidTreatmentMulty(const TopoDS_Shape& theShap
   if (myInnerSol)
   {
     myDistRef = 0.;
+    if (aTaskArray.Size())
+    {
+      mySolutionsShape1.Append(aTaskArray[0].mySolutionsShape);
+      mySolutionsShape2.Append(aTaskArray[0].mySolutionsShape);
+    }
   }
 
-  for (Standard_Integer anI = 0; anI < aTaskArray.Size(); ++anI)
-  {
-    mySolutionsShape1.Append(aTaskArray[anI].mySolutionsShape);
-    mySolutionsShape2.Append(aTaskArray[anI].mySolutionsShape);
-  }
 }
 //=======================================================================
 //function : SolidTreatment
@@ -588,6 +997,8 @@ void BRepExtrema_DistShapeShape::SolidTreatment(const TopoDS_Shape& theShape,
 Standard_Boolean BRepExtrema_DistShapeShape::Perform(const Message_ProgressRange& theRange,
                                                      const Standard_Boolean theIsMultiThread)
 {
+  CheckAndSetMutex(theIsMultiThread);
+
   myIsDone   = Standard_False;
   myInnerSol = Standard_False;
   myIsBreak  = Standard_False;
@@ -612,74 +1023,74 @@ Standard_Boolean BRepExtrema_DistShapeShape::Perform(const Message_ProgressRange
     {
       SolidTreatment(myShape1, myMapV2, aRootScope.Next(), theIsMultiThread);
     }
-
-  if (anIsSolid2 && (!myInnerSol))
-  {
+  
+    if (anIsSolid2 && (!myInnerSol))
+    {
       SolidTreatment(myShape2, myMapV1, aRootScope.Next(), theIsMultiThread);
     }
 
-  if (!myInnerSol)
-  {
-    if (!myIsInitS1) // rebuild cached data for 1st shape
+    if (!myInnerSol)
     {
-      myBV1.Clear();
-      myBE1.Clear();
-      myBF1.Clear();
+      if (!myIsInitS1) // rebuild cached data for 1st shape
+      {
+        myBV1.Clear();
+        myBE1.Clear();
+        myBF1.Clear();
 
-      BoxCalculation (myMapV1, myBV1);
-      BoxCalculation (myMapE1, myBE1);
-      BoxCalculation (myMapF1, myBF1);
+        BoxCalculation (myMapV1, myBV1);
+        BoxCalculation (myMapE1, myBE1);
+        BoxCalculation (myMapF1, myBF1);
 
-      myIsInitS1 = Standard_True;
-    }
+        myIsInitS1 = Standard_True;
+      }
 
-    if (!myIsInitS2) // rebuild cached data for 2nd shape
-    {
-      myBV2.Clear();
-      myBE2.Clear();
-      myBF2.Clear();
+      if (!myIsInitS2) // rebuild cached data for 2nd shape
+      {
+        myBV2.Clear();
+        myBE2.Clear();
+        myBF2.Clear();
 
-      BoxCalculation (myMapV2, myBV2);
-      BoxCalculation (myMapE2, myBE2);
-      BoxCalculation (myMapF2, myBF2);
+        BoxCalculation (myMapV2, myBV2);
+        BoxCalculation (myMapE2, myBE2);
+        BoxCalculation (myMapF2, myBF2);
 
-      myIsInitS2 = Standard_True;
-    }
+        myIsInitS2 = Standard_True;
+      }
 
-    if (myMapV1.Extent() && myMapV2.Extent())
-    {
-      TopoDS_Vertex V1 = TopoDS::Vertex(myMapV1(1));
-      TopoDS_Vertex V2 = TopoDS::Vertex(myMapV2(1));
-      myDistRef = DistanceInitiale(V1, V2);
-    }
-    else
-      myDistRef= 1.e30; //szv:!!!
-
-    DistanceVertVert(myMapV1, myMapV2, myBV1, myBV2, aRootScope.Next());
-    DistanceMapMap (myMapV1, myMapE2, myBV1, myBE2, aRootScope.Next());
-    DistanceMapMap (myMapE1, myMapV2, myBE1, myBV2, aRootScope.Next());
-    DistanceMapMap (myMapV1, myMapF2, myBV1, myBF2, aRootScope.Next());
-    DistanceMapMap (myMapF1, myMapV2, myBF1, myBV2, aRootScope.Next());
-    DistanceMapMap (myMapE1, myMapE2, myBE1, myBE2, aRootScope.Next());
-    DistanceMapMap (myMapE1, myMapF2, myBE1, myBF2, aRootScope.Next());
-    DistanceMapMap (myMapF1, myMapE2, myBF1, myBE2, aRootScope.Next());
-
-    if (fabs (myDistRef) > myEps)
-    {
-        DistanceMapMap (myMapF1, myMapF2, myBF1, myBF2, aRootScope.Next());
-    }
-    
-    //  Modified by Sergey KHROMOV - Tue Mar  6 11:55:03 2001 Begin
-    Standard_Integer i = 1;
-    for (; i <= mySolutionsShape1.Length(); i++)
-      if (mySolutionsShape1.Value(i).Dist() > myDistRef + myEps)
+      if (myMapV1.Extent() && myMapV2.Extent())
       {
-        mySolutionsShape1.Remove(i);
-        mySolutionsShape2.Remove(i);
+        TopoDS_Vertex V1 = TopoDS::Vertex(myMapV1(1));
+        TopoDS_Vertex V2 = TopoDS::Vertex(myMapV2(1));
+        myDistRef = DistanceInitiale(V1, V2);
       }
-    //  Modified by Sergey KHROMOV - Tue Mar  6 11:55:04 2001 End
-    myIsDone = ( mySolutionsShape1.Length() > 0 );
-  }
+      else
+        myDistRef= 1.e30; //szv:!!!
+
+      DistanceVertVert(myMapV1, myMapV2, myBV1, myBV2, aRootScope.Next());
+      DistanceMapMap (myMapV1, myMapE2, myBV1, myBE2, aRootScope.Next());
+      DistanceMapMap (myMapE1, myMapV2, myBE1, myBV2, aRootScope.Next());
+      DistanceMapMap (myMapV1, myMapF2, myBV1, myBF2, aRootScope.Next());
+      DistanceMapMap (myMapF1, myMapV2, myBF1, myBV2, aRootScope.Next());
+      DistanceMapMap (myMapE1, myMapE2, myBE1, myBE2, aRootScope.Next());
+      DistanceMapMap (myMapE1, myMapF2, myBE1, myBF2, aRootScope.Next());
+      DistanceMapMap (myMapF1, myMapE2, myBF1, myBE2, aRootScope.Next());
+
+      if (fabs (myDistRef) > myEps)
+      {
+          DistanceMapMap (myMapF1, myMapF2, myBF1, myBF2, aRootScope.Next());
+      }
+    
+      //  Modified by Sergey KHROMOV - Tue Mar  6 11:55:03 2001 Begin
+      Standard_Integer i = 1;
+      for (; i <= mySolutionsShape1.Length(); i++)
+        if (mySolutionsShape1.Value(i).Dist() > myDistRef + myEps)
+        {
+          mySolutionsShape1.Remove(i);
+          mySolutionsShape2.Remove(i);
+        }
+      //  Modified by Sergey KHROMOV - Tue Mar  6 11:55:04 2001 End
+      myIsDone = ( mySolutionsShape1.Length() > 0 );
+    }
   }
   catch (StdFail_NotDone)
   {
@@ -862,3 +1273,20 @@ void BRepExtrema_DistShapeShape::Dump(Standard_OStream& o) const
     o<<std::endl;
   } 
 }
+
+//=======================================================================
+//function : CheckAndSetMutex
+//purpose  : 
+//=======================================================================
+void BRepExtrema_DistShapeShape::CheckAndSetMutex(const Standard_Boolean theIsMultiThread)
+{
+  if (theIsMultiThread && myMutex.IsNull())
+  {
+    myMutex.reset(new Standard_HMutex());
+  }
+  else
+  {
+    myMutex = NULL;
+  }
+}
+
index ab1feae1a98801e6b04c6950b6960550c771e533..340f564b48f0ed7cfdc627ac182a89f7795d06d6 100644 (file)
@@ -26,6 +26,7 @@
 #include <TopTools_IndexedMapOfShape.hxx>
 #include <Standard_OStream.hxx>
 #include <Standard_DefineAlloc.hxx>
+#include <Standard_Mutex.hxx>
 #include <TopTools_IndexedMapOfShape.hxx>
 
 //! This class  provides tools to compute minimum distance <br>
@@ -175,6 +176,9 @@ private:
   void SolidTreatmentMulty(const TopoDS_Shape& theShape,
                            const TopTools_IndexedMapOfShape& theVertexMap,
                            const Message_ProgressRange& theRange);
+
+  void CheckAndSetMutex(const Standard_Boolean theIsMultiThread);
+
 private:
 
   Standard_Real myDistRef;
@@ -203,6 +207,7 @@ private:
   Bnd_SeqOfBox myBF2;
 
   Standard_Boolean myIsBreak;
+  mutable Handle(Standard_HMutex) myMutex;
 };
 
 #endif