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

@@ -74,7 +74,7 @@ std::filebuf Draw_Spyfile;
static std::ostream spystream(&Draw_Spyfile);
static Handle(Draw_ProgressIndicator) PInd = NULL;
static Handle(Draw_ProgressIndicator) global_Progress = NULL;
Standard_EXPORT Standard_Boolean Draw_Interprete(const char* command);
// true if complete command
@@ -240,14 +240,14 @@ Draw_Interpretor& Draw::GetInterpretor()
//function :
//purpose : Set/Get Progress Indicator
//=======================================================================
void Draw::SetProgressBar(const Handle(Draw_ProgressIndicator)& thePI)
void Draw::SetProgressBar(const Handle(Draw_ProgressIndicator)& theProgress)
{
PInd = thePI;
global_Progress = theProgress;
}
Handle(Draw_ProgressIndicator) Draw::GetProgressBar()
{
return PInd;
return global_Progress;
}
#ifndef _WIN32

View File

@@ -188,7 +188,7 @@ public:
Standard_EXPORT static void Repaint();
//! sets progress indicator
Standard_EXPORT static void SetProgressBar (const Handle(Draw_ProgressIndicator)& thePI);
Standard_EXPORT static void SetProgressBar (const Handle(Draw_ProgressIndicator)& theProgress);
//! gets progress indicator
Standard_EXPORT static Handle(Draw_ProgressIndicator) GetProgressBar();

View File

@@ -17,8 +17,12 @@
#include <Draw_ProgressIndicator.hxx>
#include <Message.hxx>
#include <Message_Messenger.hxx>
#include <Message_ProgressScale.hxx>
#include <Message_ProgressScope.hxx>
#include <NCollection_List.hxx>
#include <Precision.hxx>
#include <OSD.hxx>
#include <OSD_Exception_CTRL_BREAK.hxx>
#include <OSD_Thread.hxx>
#include <stdio.h>
#include <time.h>
@@ -29,15 +33,16 @@ IMPLEMENT_STANDARD_RTTIEXT(Draw_ProgressIndicator,Message_ProgressIndicator)
//purpose :
//=======================================================================
Draw_ProgressIndicator::Draw_ProgressIndicator (const Draw_Interpretor &di, Standard_Real theUpdateThreshold)
: myTextMode ( DefaultTextMode() ),
: myTclMode ( DefaultTclMode() ),
myConsoleMode ( DefaultConsoleMode() ),
myGraphMode ( DefaultGraphMode() ),
myTclOutput ( DefaultTclOutput() ),
myDraw ( (Draw_Interpretor*)&di ),
myShown ( Standard_False ),
myBreak ( Standard_False ),
myUpdateThreshold ( 0.01 * theUpdateThreshold ),
myLastPosition ( -1. ),
myStartTime ( 0 )
myStartTime ( 0 ),
myGuiThreadId (OSD_Thread::Current())
{
}
@@ -73,23 +78,27 @@ void Draw_ProgressIndicator::Reset()
//purpose :
//=======================================================================
Standard_Boolean Draw_ProgressIndicator::Show(const Standard_Boolean force)
void Draw_ProgressIndicator::Show (const Message_ProgressScope& theScope, const Standard_Boolean force)
{
if ( ! myGraphMode && ! myTextMode )
return Standard_False;
if (!myGraphMode && !myTclMode && !myConsoleMode)
return;
// remember time of the first call to Show as process start time
if ( ! myStartTime )
{
time_t aTimeT;
time ( &aTimeT );
myStartTime = (Standard_Size)aTimeT;
if (!myStartTime)
{
time_t aTimeT;
time(&aTimeT);
myStartTime = (Standard_Size)aTimeT;
}
}
// unless show is forced, show updated state only if at least 1% progress has been reached since the last update
Standard_Real aPosition = GetPosition();
if ( ! force && aPosition < 1. && Abs (aPosition - myLastPosition) < myUpdateThreshold)
return Standard_False; // return if update interval has not elapsed
return; // return if update interval has not elapsed
myLastPosition = aPosition;
// Prepare textual progress info
@@ -97,17 +106,19 @@ Standard_Boolean Draw_ProgressIndicator::Show(const Standard_Boolean force)
aText.setf (std::ios::fixed, std:: ios::floatfield);
aText.precision(0);
aText << "Progress: " << 100. * GetPosition() << "%";
for ( Standard_Integer i=GetNbScopes(); i >=1; i-- ) {
const Message_ProgressScale &scale = GetScope ( i );
if ( scale.GetName().IsNull() ) continue; // skip unnamed scopes
aText << " " << scale.GetName()->ToCString() << ": ";
NCollection_List<const Message_ProgressScope*> aScopes;
for (const Message_ProgressScope* aPS = &theScope; aPS; aPS = aPS->Parent())
aScopes.Prepend(aPS);
for (NCollection_List<const Message_ProgressScope*>::Iterator it(aScopes); it.More(); it.Next())
{
const Message_ProgressScope* aPS = it.Value();
if (!aPS->Name()) continue; // skip unnamed scopes
aText << " " << aPS->Name() << ": ";
// if scope has subscopes, print end of subscope as it s current position
Standard_Real locPos = ( (i >1 && GetPosition()!=0) ? GetScope ( i-1 ).GetLast() : GetPosition() );
// print progress info differently for finite and infinite scopes
if ( scale.GetInfinite() )
Standard_Real aVal = aPS->Value();
if (aPS->IsInfinite())
{
Standard_Real aVal = scale.BaseToLocal(locPos);
if (Precision::IsInfinite(aVal))
{
aText << "finished";
@@ -119,13 +130,14 @@ Standard_Boolean Draw_ProgressIndicator::Show(const Standard_Boolean force)
}
else
{
aText << scale.BaseToLocal ( locPos ) << " / " << scale.GetMax();
aText << aVal << " / " << aPS->MaxValue();
}
}
// Show graphic progress bar
if ( myGraphMode ) {
// Show graphic progress bar.
// It will be updated only within GUI thread.
if (myGraphMode && myGuiThreadId == OSD_Thread::Current())
{
// In addition, write elapsed/estimated/remaining time
if ( GetPosition() > 0.01 ) {
time_t aTimeT;
@@ -153,25 +165,21 @@ Standard_Boolean Draw_ProgressIndicator::Show(const Standard_Boolean force)
aCommand.setf(std::ios::fixed, std::ios::floatfield);
aCommand.precision(0);
aCommand << ".xprogress.bar coords progress 2 2 " << (1 + 400 * GetPosition()) << " 21;";
aCommand << ".xprogress.bar coords progress_next 2 2 " << (1 + 400 * GetScope(1).GetLast()) << " 21;";
aCommand << ".xprogress.bar coords progress_next 2 2 " << (1 + 400 * theScope.GetPortion()) << " 21;";
aCommand << ".xprogress.text configure -text \"" << aText.str() << "\";";
aCommand << "update";
myDraw->Eval (aCommand.str().c_str());
}
// Print textual progress info
if (myTextMode)
if (myTclMode && myDraw)
{
if (myTclOutput && myDraw)
{
*myDraw << aText.str().c_str() << "\n";
}
else
{
std::cout << aText.str().c_str() << "\n";
}
*myDraw << aText.str().c_str() << "\n";
}
if (myConsoleMode)
{
std::cout << aText.str().c_str() << "\n";
}
return Standard_True;
}
//=======================================================================
@@ -181,32 +189,65 @@ Standard_Boolean Draw_ProgressIndicator::Show(const Standard_Boolean force)
Standard_Boolean Draw_ProgressIndicator::UserBreak()
{
if ( StopIndicator() == this ) {
if ( StopIndicator() == this )
{
// std::cout << "Progress Indicator - User Break: " << StopIndicator() << ", " << (void*)this << std::endl;
myBreak = Standard_True;
myDraw->Eval ( "XProgress -stop 0" );
}
else
{
// treatment of Ctrl-Break signal
try
{
OSD::ControlBreak();
}
catch (OSD_Exception_CTRL_BREAK)
{
myBreak = Standard_True;
}
}
return myBreak;
}
//=======================================================================
//function : SetTextMode
//purpose : Sets text output mode (on/off)
//function : SetTclMode
//purpose : Sets Tcl output mode (on/off)
//=======================================================================
void Draw_ProgressIndicator::SetTextMode(const Standard_Boolean theTextMode)
void Draw_ProgressIndicator::SetTclMode(const Standard_Boolean theTclMode)
{
myTextMode = theTextMode;
myTclMode = theTclMode;
}
//=======================================================================
//function : GetTextMode
//purpose : Returns text output mode (on/off)
//function : GetTclMode
//purpose : Returns Tcl output mode (on/off)
//=======================================================================
Standard_Boolean Draw_ProgressIndicator::GetTextMode() const
Standard_Boolean Draw_ProgressIndicator::GetTclMode() const
{
return myTextMode;
return myTclMode;
}
//=======================================================================
//function : SetConsoleMode
//purpose : Sets Console output mode (on/off)
//=======================================================================
void Draw_ProgressIndicator::SetConsoleMode(const Standard_Boolean theMode)
{
myConsoleMode = theMode;
}
//=======================================================================
//function : GetConsoleMode
//purpose : Returns Console output mode (on/off)
//=======================================================================
Standard_Boolean Draw_ProgressIndicator::GetConsoleMode() const
{
return myConsoleMode;
}
//=======================================================================
@@ -230,14 +271,25 @@ Standard_Boolean Draw_ProgressIndicator::GetGraphMode() const
}
//=======================================================================
//function : DefaultTextMode
//function : DefaultTclMode
//purpose :
//=======================================================================
Standard_Boolean &Draw_ProgressIndicator::DefaultTextMode()
Standard_Boolean &Draw_ProgressIndicator::DefaultTclMode()
{
static Standard_Boolean defTextMode = Standard_False;
return defTextMode;
static Standard_Boolean defTclMode = Standard_False;
return defTclMode;
}
//=======================================================================
//function : DefaultConsoleMode
//purpose :
//=======================================================================
Standard_Boolean &Draw_ProgressIndicator::DefaultConsoleMode()
{
static Standard_Boolean defConsoleMode = Standard_False;
return defConsoleMode;
}
//=======================================================================
@@ -251,17 +303,6 @@ Standard_Boolean &Draw_ProgressIndicator::DefaultGraphMode()
return defGraphMode;
}
//=======================================================================
//function : DefaultTclOutput
//purpose :
//=======================================================================
Standard_Boolean &Draw_ProgressIndicator::DefaultTclOutput()
{
static Standard_Boolean defTclOutput = Standard_False;
return defTclOutput;
}
//=======================================================================
//function : StopIndicator
//purpose :

View File

@@ -43,41 +43,44 @@ public:
//! Destructor; calls Reset()
Standard_EXPORT ~Draw_ProgressIndicator();
//! Sets text output mode (on/off)
Standard_EXPORT void SetTextMode (const Standard_Boolean theTextMode);
//! Gets text output mode (on/off)
Standard_EXPORT Standard_Boolean GetTextMode() const;
//! Sets tcl output mode (on/off).
Standard_EXPORT void SetTclMode (const Standard_Boolean theTclMode);
//! Gets tcl output mode (on/off).
Standard_EXPORT Standard_Boolean GetTclMode() const;
//! Sets console output mode (on/off).
//! If it is on then progress is shown in the standard output.
Standard_EXPORT void SetConsoleMode(const Standard_Boolean theMode);
//! Gets console output mode (on/off)
Standard_EXPORT Standard_Boolean GetConsoleMode() const;
//! Sets graphical output mode (on/off)
Standard_EXPORT void SetGraphMode (const Standard_Boolean theGraphMode);
//! Gets graphical output mode (on/off)
Standard_EXPORT Standard_Boolean GetGraphMode() const;
//! Sets tcl output mode (on/off)
void SetTclOutput (const Standard_Boolean theTclOutput) { myTclOutput = theTclOutput; }
//! Gets tcl output mode (on/off)
Standard_Boolean GetTclOutput() const { return myTclOutput; }
//! Clears/erases opened TCL windows if any
//! and sets myBreak to False
Standard_EXPORT virtual void Reset() Standard_OVERRIDE;
//! Defines method Show of Progress Indicator
Standard_EXPORT virtual Standard_Boolean Show (const Standard_Boolean force = Standard_True) Standard_OVERRIDE;
Standard_EXPORT virtual void Show (const Message_ProgressScope& theScope,
const Standard_Boolean force = Standard_True) Standard_OVERRIDE;
//! Redefines method UserBreak of Progress Indicator
Standard_EXPORT virtual Standard_Boolean UserBreak() Standard_OVERRIDE;
Standard_EXPORT static Standard_Boolean& DefaultTextMode();
//! Get/Set default values for output modes
Standard_EXPORT static Standard_Boolean& DefaultGraphMode();
//! Get/Set default value for tcl mode
Standard_EXPORT static Standard_Boolean& DefaultTclMode();
//! Get/Set default values for tcl output mode
Standard_EXPORT static Standard_Boolean& DefaultTclOutput();
//! Get/Set default value for console mode
Standard_EXPORT static Standard_Boolean& DefaultConsoleMode();
//! Get/Set default value for graph mode
Standard_EXPORT static Standard_Boolean& DefaultGraphMode();
//! Internal method for implementation of UserBreak mechanism;
//! note that it uses static variable and thus not thread-safe!
@@ -86,15 +89,16 @@ public:
DEFINE_STANDARD_RTTIEXT(Draw_ProgressIndicator,Message_ProgressIndicator)
private:
Standard_Boolean myTextMode;
Standard_Boolean myTclMode;
Standard_Boolean myConsoleMode;
Standard_Boolean myGraphMode;
Standard_Boolean myTclOutput;
Draw_Interpretor* myDraw;
Standard_Boolean myShown;
Standard_Boolean myBreak;
Standard_Real myUpdateThreshold;
Standard_Real myLastPosition;
Standard_Size myStartTime;
Standard_ThreadId myGuiThreadId;
};
#endif // _Draw_ProgressIndicator_HeaderFile

View File

@@ -157,9 +157,6 @@ static Standard_Integer save(Draw_Interpretor& di, Standard_Integer n, const cha
// find a tool
Draw_SaveAndRestore* tool = Draw_First;
Handle(Draw_ProgressIndicator) progress = new Draw_ProgressIndicator ( di, 1 );
progress->SetScale ( 0, 100, 1 );
progress->NewScope(100,"Writing");
progress->Show();
while (tool) {
if (tool->Test(D)) break;
@@ -176,8 +173,6 @@ static Standard_Integer save(Draw_Interpretor& di, Standard_Integer n, const cha
return 1;
}
Draw::SetProgressBar( 0 );
progress->EndScope();
progress->Show();
}
os << "0\n\n";
@@ -222,8 +217,7 @@ static Standard_Integer restore(Draw_Interpretor& di, Standard_Integer n, const
if (!in.fail()) {
// search a tool
Handle(Draw_ProgressIndicator) progress = new Draw_ProgressIndicator ( di, 1 );
progress->NewScope(100,"Reading");
progress->Show();
Draw::SetProgressBar(progress);
Draw_SaveAndRestore* tool = Draw_First;
Draw_SaveAndRestore* aDBRepTool = NULL;
@@ -232,7 +226,6 @@ static Standard_Integer restore(Draw_Interpretor& di, Standard_Integer n, const
if (!strcmp(typ,toolName)) break;
if (!strcmp("DBRep_DrawableShape",toolName))
aDBRepTool = tool;
Draw::SetProgressBar(progress);
tool = tool->Next();
}
@@ -254,8 +247,6 @@ static Standard_Integer restore(Draw_Interpretor& di, Standard_Integer n, const
return 1;
}
Draw::SetProgressBar( 0 );
progress->EndScope();
progress->Show();
}
di << name;