From 1318c6b198cd753354d53d6d2ed9bd62913697bd Mon Sep 17 00:00:00 2001 From: asuraven Date: Wed, 25 Aug 2021 21:19:00 +0300 Subject: [PATCH] 0032539: Parallelize distance --- .../BRepExtrema_DistShapeShape.cxx | 692 ++++++++++++++---- .../BRepExtrema_DistShapeShape.hxx | 5 + 2 files changed, 565 insertions(+), 132 deletions(-) diff --git a/src/BRepExtrema/BRepExtrema_DistShapeShape.cxx b/src/BRepExtrema/BRepExtrema_DistShapeShape.cxx index 1e808bc591..aec844ff08 100644 --- a/src/BRepExtrema/BRepExtrema_DistShapeShape.cxx +++ b/src/BRepExtrema/BRepExtrema_DistShapeShape.cxx @@ -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 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 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* 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* 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::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::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 > 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 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 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< #include #include +#include #include //! This class provides tools to compute minimum distance
@@ -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 -- 2.39.5