1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-09 13:22:24 +03:00

0025748: Parallel version of progress indicator

Progress indication mechanism is refactored to support incrementing progress within multithreaded algorithms.

The class Message_ProgressIndicator is only an interface to the user application.
It accumulates the progress provided by progress scopes.
The counter is protected by mutex for thread-safety.

The new class Message_ProgressScope replacing Message_ProgressSentry should be used to advance the progress.
The scopes are nested to each other to reflect the nested nature of operations.
The new class Message_ProgressRange should be used to pass the progress to sub-scopes.

All OCCT algorithms involving progress indication have been updated to new API.

Improvements in Draw_ProgressIndicator:
- Separate console mode has been added in order to make possible to put the progress into std::cout instead
  or in addition to the draw interpreter, instead of trigger option "-tclOutput".
- Treatment of Ctrl-Break signal has been added.
  Now any operation can be aborted by Ctrl-C or Ctrl-Break keystroke.

Added new test case 'perf fclasses progr_par' for testing of parallel work of the progress.
This commit is contained in:
msv
2020-07-10 14:19:31 +03:00
committed by abv
parent 99289bed0a
commit 7e785937b3
271 changed files with 3701 additions and 3149 deletions

View File

@@ -21,7 +21,7 @@
#include <BRep_Tool.hxx>
#include <Message.hxx>
#include <Message_Messenger.hxx>
#include <Message_ProgressSentry.hxx>
#include <Message_ProgressScope.hxx>
#include <OSD_OpenFile.hxx>
#include <OSD_ThreadPool.hxx>
@@ -42,13 +42,13 @@ public:
//! Main constructor.
CafReader_GltfReaderFunctor (RWGltf_CafReader* myCafReader,
NCollection_Vector<TopoDS_Face>& theFaceList,
Message_ProgressSentry& theSentry,
const Message_ProgressRange& theProgress,
const OSD_ThreadPool::Launcher& theThreadPool,
const TCollection_AsciiString& theErrPrefix)
: myCafReader (myCafReader),
myFaceList (&theFaceList),
mySentry (&theSentry),
myErrPrefix (theErrPrefix),
myProgress (theProgress, "Loading glTF triangulation", Max (1, theFaceList.Size())),
myThreadPool(theThreadPool),
myTlsData (theThreadPool.LowerThreadIndex(), theThreadPool.UpperThreadIndex())
{
@@ -77,11 +77,11 @@ public:
if (myThreadPool.HasThreads())
{
Standard_Mutex::Sentry aLock (&myMutex);
mySentry->Next();
myProgress.Next();
}
else
{
mySentry->Next();
myProgress.Next();
}
}
@@ -89,13 +89,11 @@ private:
RWGltf_CafReader* myCafReader;
NCollection_Vector<TopoDS_Face>* myFaceList;
Message_ProgressSentry* mySentry;
TCollection_AsciiString myErrPrefix;
mutable Standard_Mutex myMutex;
mutable Message_ProgressScope myProgress;
const OSD_ThreadPool::Launcher& myThreadPool;
mutable NCollection_Array1<GltfReaderTLS>
myTlsData;
mutable NCollection_Array1<GltfReaderTLS> myTlsData;
};
//================================================================
@@ -116,9 +114,12 @@ RWGltf_CafReader::RWGltf_CafReader()
// Purpose :
//================================================================
Standard_Boolean RWGltf_CafReader::performMesh (const TCollection_AsciiString& theFile,
const Handle(Message_ProgressIndicator)& theProgress,
const Message_ProgressRange& theProgress,
const Standard_Boolean theToProbe)
{
Message_ProgressScope aPSentry (theProgress, "Reading glTF", 2);
aPSentry.Show();
std::ifstream aFile;
OSD_OpenStream (aFile, theFile.ToCString(), std::ios::in | std::ios::binary);
if (!aFile.is_open()
@@ -256,13 +257,13 @@ Standard_Boolean RWGltf_CafReader::performMesh (const TCollection_AsciiString& t
}
#endif
if (!aDoc.Parse (theProgress))
if (!aDoc.Parse (aPSentry.Next()))
{
return false;
}
if (!theToProbe
&& !readLateData (aDoc.FaceList(), theFile, theProgress))
&& !readLateData (aDoc.FaceList(), theFile, aPSentry.Next()))
{
return false;
}
@@ -286,14 +287,13 @@ Handle(RWGltf_PrimitiveArrayReader) RWGltf_CafReader::createMeshReaderContext()
//================================================================
Standard_Boolean RWGltf_CafReader::readLateData (NCollection_Vector<TopoDS_Face>& theFaces,
const TCollection_AsciiString& theFile,
const Handle(Message_ProgressIndicator)& theProgress)
const Message_ProgressRange& theProgress)
{
Message_ProgressSentry aPSentryTris (theProgress, "Loading glTF triangulation", 0, Max (1, theFaces.Size()), 1);
const Handle(OSD_ThreadPool)& aThreadPool = OSD_ThreadPool::DefaultPool();
const int aNbThreads = myToParallel ? Min (theFaces.Size(), aThreadPool->NbDefaultThreadsToLaunch()) : 1;
OSD_ThreadPool::Launcher aLauncher (*aThreadPool, aNbThreads);
CafReader_GltfReaderFunctor aFunctor (this, theFaces, aPSentryTris, aLauncher,
CafReader_GltfReaderFunctor aFunctor (this, theFaces, theProgress, aLauncher,
TCollection_AsciiString ("File '") + theFile + "' defines invalid glTF!\n");
aLauncher.Perform (theFaces.Lower(), theFaces.Upper() + 1, aFunctor);
return Standard_True;

View File

@@ -15,6 +15,7 @@
#ifndef _RWGltf_CafReader_HeaderFile
#define _RWGltf_CafReader_HeaderFile
#include <Message_ProgressRange.hxx>
#include <NCollection_Vector.hxx>
#include <RWMesh_CafReader.hxx>
#include <TopoDS_Face.hxx>
@@ -52,7 +53,7 @@ protected:
//! Read the mesh from specified file.
Standard_EXPORT virtual Standard_Boolean performMesh (const TCollection_AsciiString& theFile,
const Handle(Message_ProgressIndicator)& theProgress,
const Message_ProgressRange& theProgress,
const Standard_Boolean theToProbe) Standard_OVERRIDE;
//! Create primitive array reader context.
@@ -63,7 +64,7 @@ protected:
//! Read late data from RWGltf_GltfLatePrimitiveArray stored as Poly_Triangulation within faces.
Standard_EXPORT virtual Standard_Boolean readLateData (NCollection_Vector<TopoDS_Face>& theFaces,
const TCollection_AsciiString& theFile,
const Handle(Message_ProgressIndicator)& theProgress);
const Message_ProgressRange& theProgress);
protected:
class CafReader_GltfReaderFunctor;

View File

@@ -16,7 +16,7 @@
#include <gp_Quaternion.hxx>
#include <Message.hxx>
#include <Message_Messenger.hxx>
#include <Message_ProgressSentry.hxx>
#include <Message_ProgressScope.hxx>
#include <NCollection_DataMap.hxx>
#include <OSD_OpenFile.hxx>
#include <OSD_File.hxx>
@@ -285,7 +285,7 @@ void RWGltf_CafWriter::saveIndices (RWGltf_GltfFace& theGltfFace,
// =======================================================================
bool RWGltf_CafWriter::Perform (const Handle(TDocStd_Document)& theDocument,
const TColStd_IndexedDataMapOfStringString& theFileInfo,
const Handle(Message_ProgressIndicator)& theProgress)
const Message_ProgressRange& theProgress)
{
TDF_LabelSequence aRoots;
Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool (theDocument->Main());
@@ -301,21 +301,20 @@ bool RWGltf_CafWriter::Perform (const Handle(TDocStd_Document)& theDocument,
const TDF_LabelSequence& theRootLabels,
const TColStd_MapOfAsciiString* theLabelFilter,
const TColStd_IndexedDataMapOfStringString& theFileInfo,
const Handle(Message_ProgressIndicator)& theProgress)
const Message_ProgressRange& theProgress)
{
Message_ProgressSentry aPSentry (theProgress, "Writing glTF file", 0, 2, 1);
if (!writeBinData (theDocument, theRootLabels, theLabelFilter, theProgress))
Message_ProgressScope aPSentry (theProgress, "Writing glTF file", 2);
if (!writeBinData (theDocument, theRootLabels, theLabelFilter, aPSentry.Next()))
{
return false;
}
aPSentry.Next();
if (!aPSentry.More())
{
return false;
}
return writeJson (theDocument, theRootLabels, theLabelFilter, theFileInfo, theProgress);
return writeJson (theDocument, theRootLabels, theLabelFilter, theFileInfo, aPSentry.Next());
}
// =======================================================================
@@ -325,7 +324,7 @@ bool RWGltf_CafWriter::Perform (const Handle(TDocStd_Document)& theDocument,
bool RWGltf_CafWriter::writeBinData (const Handle(TDocStd_Document)& theDocument,
const TDF_LabelSequence& theRootLabels,
const TColStd_MapOfAsciiString* theLabelFilter,
const Handle(Message_ProgressIndicator)& theProgress)
const Message_ProgressRange& theProgress)
{
myBuffViewPos.ByteOffset = 0;
myBuffViewPos.ByteLength = 0;
@@ -355,7 +354,7 @@ bool RWGltf_CafWriter::writeBinData (const Handle(TDocStd_Document)& theDocument
return false;
}
Message_ProgressSentry aPSentryBin (theProgress, "Binary data", 0, 4, 1);
Message_ProgressScope aPSentryBin (theProgress, "Binary data", 4);
Standard_Integer aNbAccessors = 0;
@@ -552,13 +551,13 @@ bool RWGltf_CafWriter::writeJson (const Handle(TDocStd_Document)& theDocument,
const TDF_LabelSequence& theRootLabels,
const TColStd_MapOfAsciiString* theLabelFilter,
const TColStd_IndexedDataMapOfStringString& theFileInfo,
const Handle(Message_ProgressIndicator)& theProgress)
const Message_ProgressRange& theProgress)
{
#ifdef HAVE_RAPIDJSON
myWriter.reset();
// write vertex arrays
Message_ProgressSentry aPSentryBin (theProgress, "Header data", 0, 2, 1);
Message_ProgressScope aPSentryBin (theProgress, "Header data", 2);
const Standard_Integer aBinDataBufferId = 0;
const Standard_Integer aDefSamplerId = 0;

View File

@@ -26,7 +26,7 @@
#include <memory>
class Message_ProgressIndicator;
class Message_ProgressRange;
class RWMesh_FaceIterator;
class RWGltf_GltfOStreamWriter;
class RWGltf_GltfMaterialMap;
@@ -93,7 +93,7 @@ public:
const TDF_LabelSequence& theRootLabels,
const TColStd_MapOfAsciiString* theLabelFilter,
const TColStd_IndexedDataMapOfStringString& theFileInfo,
const Handle(Message_ProgressIndicator)& theProgress);
const Message_ProgressRange& theProgress);
//! Write glTF file and associated binary file.
//! Triangulation data should be precomputed within shapes!
@@ -103,7 +103,7 @@ public:
//! @return FALSE on file writing failure
Standard_EXPORT virtual bool Perform (const Handle(TDocStd_Document)& theDocument,
const TColStd_IndexedDataMapOfStringString& theFileInfo,
const Handle(Message_ProgressIndicator)& theProgress);
const Message_ProgressRange& theProgress);
protected:
@@ -117,7 +117,7 @@ protected:
Standard_EXPORT virtual bool writeBinData (const Handle(TDocStd_Document)& theDocument,
const TDF_LabelSequence& theRootLabels,
const TColStd_MapOfAsciiString* theLabelFilter,
const Handle(Message_ProgressIndicator)& theProgress);
const Message_ProgressRange& theProgress);
//! Write JSON file with glTF structure (should be called after writeBinData()).
//! @param theDocument [in] input document
@@ -130,7 +130,7 @@ protected:
const TDF_LabelSequence& theRootLabels,
const TColStd_MapOfAsciiString* theLabelFilter,
const TColStd_IndexedDataMapOfStringString& theFileInfo,
const Handle(Message_ProgressIndicator)& theProgress);
const Message_ProgressRange& theProgress);
protected:

View File

@@ -18,7 +18,7 @@
#include <gp_Quaternion.hxx>
#include <Message.hxx>
#include <Message_Messenger.hxx>
#include <Message_ProgressSentry.hxx>
#include <Message_ProgressScope.hxx>
#include <OSD_File.hxx>
#include <OSD_OpenFile.hxx>
#include <OSD_Path.hxx>
@@ -971,7 +971,7 @@ bool RWGltf_GltfJsonParser::gltfParseTextureInBufferView (Handle(Image_Texture)&
// function : gltfParseScene
// purpose :
// =======================================================================
bool RWGltf_GltfJsonParser::gltfParseScene (const Handle(Message_ProgressIndicator)& theProgress)
bool RWGltf_GltfJsonParser::gltfParseScene (const Message_ProgressRange& theProgress)
{
// search default scene
const RWGltf_JsonValue* aDefScene = myGltfRoots[RWGltf_GltfRootElement_Scenes].FindChild (*myGltfRoots[RWGltf_GltfRootElement_Scene].Root());
@@ -998,7 +998,7 @@ bool RWGltf_GltfJsonParser::gltfParseScene (const Handle(Message_ProgressIndicat
// =======================================================================
bool RWGltf_GltfJsonParser::gltfParseSceneNodes (TopTools_SequenceOfShape& theShapeSeq,
const RWGltf_JsonValue& theSceneNodes,
const Handle(Message_ProgressIndicator)& theProgress)
const Message_ProgressRange& theProgress)
{
if (!theSceneNodes.IsArray())
{
@@ -1006,9 +1006,9 @@ bool RWGltf_GltfJsonParser::gltfParseSceneNodes (TopTools_SequenceOfShape& theSh
return false;
}
Message_ProgressSentry aPSentry (theProgress, "Reading scene nodes", 0, theSceneNodes.Size(), 1);
Message_ProgressScope aPS (theProgress, "Reading scene nodes", theSceneNodes.Size());
for (rapidjson::Value::ConstValueIterator aSceneNodeIter = theSceneNodes.Begin();
aSceneNodeIter != theSceneNodes.End() && aPSentry.More(); ++aSceneNodeIter, aPSentry.Next())
aSceneNodeIter != theSceneNodes.End() && aPS.More(); ++aSceneNodeIter)
{
const RWGltf_JsonValue* aSceneNode = myGltfRoots[RWGltf_GltfRootElement_Nodes].FindChild (*aSceneNodeIter);
if (aSceneNode == NULL)
@@ -1018,7 +1018,7 @@ bool RWGltf_GltfJsonParser::gltfParseSceneNodes (TopTools_SequenceOfShape& theSh
}
TopoDS_Shape aNodeShape;
if (!gltfParseSceneNode (aNodeShape, getKeyString (*aSceneNodeIter), *aSceneNode, theProgress))
if (!gltfParseSceneNode (aNodeShape, getKeyString (*aSceneNodeIter), *aSceneNode, aPS.Next()))
{
return false;
}
@@ -1045,7 +1045,7 @@ bool RWGltf_GltfJsonParser::gltfParseSceneNodes (TopTools_SequenceOfShape& theSh
bool RWGltf_GltfJsonParser::gltfParseSceneNode (TopoDS_Shape& theNodeShape,
const TCollection_AsciiString& theSceneNodeId,
const RWGltf_JsonValue& theSceneNode,
const Handle(Message_ProgressIndicator)& theProgress)
const Message_ProgressRange& theProgress)
{
const RWGltf_JsonValue* aName = findObjectMember (theSceneNode, "name");
//const RWGltf_JsonValue* aJointName = findObjectMember (theSceneNode, "jointName");
@@ -1243,9 +1243,9 @@ bool RWGltf_GltfJsonParser::gltfParseSceneNode (TopoDS_Shape& theNodeShape,
&& aMeshes_1->IsArray())
{
// glTF 1.0
Message_ProgressSentry aPSentry (theProgress, "Reading scene meshes", 0, aMeshes_1->Size(), 1);
Message_ProgressScope aPS (theProgress, "Reading scene meshes", aMeshes_1->Size());
for (rapidjson::Value::ConstValueIterator aMeshIter = aMeshes_1->Begin();
aMeshIter != aMeshes_1->End() && aPSentry.More(); ++aMeshIter, aPSentry.Next())
aMeshIter != aMeshes_1->End() && aPS.More(); ++aMeshIter)
{
const RWGltf_JsonValue* aMesh = myGltfRoots[RWGltf_GltfRootElement_Meshes].FindChild (*aMeshIter);
if (aMesh == NULL)
@@ -1257,7 +1257,7 @@ bool RWGltf_GltfJsonParser::gltfParseSceneNode (TopoDS_Shape& theNodeShape,
}
TopoDS_Shape aMeshShape;
if (!gltfParseMesh (aMeshShape, getKeyString (*aMeshIter), *aMesh, theProgress))
if (!gltfParseMesh (aMeshShape, getKeyString (*aMeshIter), *aMesh, aPS.Next()))
{
theNodeShape = aNodeShape;
bindNodeShape (theNodeShape, aNodeLoc, theSceneNodeId, aName);
@@ -1315,7 +1315,7 @@ bool RWGltf_GltfJsonParser::gltfParseSceneNode (TopoDS_Shape& theNodeShape,
bool RWGltf_GltfJsonParser::gltfParseMesh (TopoDS_Shape& theMeshShape,
const TCollection_AsciiString& theMeshId,
const RWGltf_JsonValue& theMesh,
const Handle(Message_ProgressIndicator)& theProgress)
const Message_ProgressRange& theProgress)
{
const RWGltf_JsonValue* aName = findObjectMember (theMesh, "name");
const RWGltf_JsonValue* aPrims = findObjectMember (theMesh, "primitives");
@@ -1398,7 +1398,7 @@ bool RWGltf_GltfJsonParser::gltfParseMesh (TopoDS_Shape& theMeshShape,
bool RWGltf_GltfJsonParser::gltfParsePrimArray (const Handle(RWGltf_GltfLatePrimitiveArray)& theMeshData,
const TCollection_AsciiString& theMeshId,
const RWGltf_JsonValue& thePrimArray,
const Handle(Message_ProgressIndicator)& /*theProgress*/)
const Message_ProgressRange& /*theProgress*/)
{
const RWGltf_JsonValue* anAttribs = findObjectMember (thePrimArray, "attributes");
const RWGltf_JsonValue* anIndices = findObjectMember (thePrimArray, "indices");
@@ -1916,9 +1916,9 @@ void RWGltf_GltfJsonParser::bindNamedShape (TopoDS_Shape& theShape,
// function : Parse
// purpose :
// =======================================================================
bool RWGltf_GltfJsonParser::Parse (const Handle(Message_ProgressIndicator)& theProgress)
bool RWGltf_GltfJsonParser::Parse (const Message_ProgressRange& theProgress)
{
Message_ProgressSentry aPSentry (theProgress, "Reading Gltf", 0, 2, 1);
Message_ProgressScope aPS (theProgress, "Parsing glTF", 1);
#ifdef HAVE_RAPIDJSON
{
if (!gltfParseRoots())
@@ -1928,13 +1928,12 @@ bool RWGltf_GltfJsonParser::Parse (const Handle(Message_ProgressIndicator)& theP
gltfParseAsset();
gltfParseMaterials();
if (!gltfParseScene (theProgress))
if (!gltfParseScene (aPS.Next()))
{
return false;
}
}
aPSentry.Next();
if (!aPSentry.More())
if (!aPS.More())
{
return false;
}

View File

@@ -17,6 +17,7 @@
#include <Graphic3d_Vec.hxx>
#include <Message_Gravity.hxx>
#include <Message_ProgressScope.hxx>
#include <NCollection_DataMap.hxx>
#include <NCollection_IndexedMap.hxx>
#include <RWGltf_GltfLatePrimitiveArray.hxx>
@@ -112,7 +113,7 @@ public:
void SetMeshNameAsFallback (bool theToFallback) { myUseMeshNameAsFallback = theToFallback; }
//! Parse glTF document.
Standard_EXPORT bool Parse (const Handle(Message_ProgressIndicator)& theProgress);
Standard_EXPORT bool Parse (const Message_ProgressRange& theProgress);
//! Return face list for loading triangulation.
NCollection_Vector<TopoDS_Face>& FaceList() { return myFaceList; }
@@ -124,7 +125,7 @@ protected:
Standard_EXPORT bool gltfParseRoots();
//! Parse default scene.
Standard_EXPORT bool gltfParseScene (const Handle(Message_ProgressIndicator)& theProgress);
Standard_EXPORT bool gltfParseScene (const Message_ProgressRange& theProgress);
//! Parse document metadata.
Standard_EXPORT void gltfParseAsset();
@@ -171,25 +172,25 @@ protected:
//! Parse scene array of nodes recursively.
Standard_EXPORT bool gltfParseSceneNodes (TopTools_SequenceOfShape& theShapeSeq,
const RWGltf_JsonValue& theSceneNodes,
const Handle(Message_ProgressIndicator)& theProgress);
const Message_ProgressRange& theProgress);
//! Parse scene node recursively.
Standard_EXPORT bool gltfParseSceneNode (TopoDS_Shape& theNodeShape,
const TCollection_AsciiString& theSceneNodeId,
const RWGltf_JsonValue& theSceneNode,
const Handle(Message_ProgressIndicator)& theProgress);
const Message_ProgressRange& theProgress);
//! Parse mesh element.
Standard_EXPORT bool gltfParseMesh (TopoDS_Shape& theMeshShape,
const TCollection_AsciiString& theMeshId,
const RWGltf_JsonValue& theMesh,
const Handle(Message_ProgressIndicator)& theProgress);
const Message_ProgressRange& theProgress);
//! Parse primitive array.
Standard_EXPORT bool gltfParsePrimArray (const Handle(RWGltf_GltfLatePrimitiveArray)& theMeshData,
const TCollection_AsciiString& theMeshName,
const RWGltf_JsonValue& thePrimArray,
const Handle(Message_ProgressIndicator)& theProgress);
const Message_ProgressRange& theProgress);
//! Parse accessor.
Standard_EXPORT bool gltfParseAccessor (const Handle(RWGltf_GltfLatePrimitiveArray)& theMeshData,