mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-03 17:56:21 +03:00
0031763: Foundation Classes - reporting of progress within parallel algorithms
Classes Message_ProgressRange and Message_ProgressScope are improved to store start point of the range. Method Message_ProgressScope::Value() is improved to compute the value in the current scope from the actual current value of the global progress. Description of Message_ProgressScope class is improved. Off-topic: - method Message_ProgressScope::Relieve() is renamed to Close() for semantic consistency - article in Upgrade Guide is revised and corrected
This commit is contained in:
parent
88610dfc0e
commit
7a3e8aad74
@ -1935,26 +1935,38 @@ Offset direction, which used in class Adaptor2d_OffsetCurve for evaluating value
|
||||
|
||||
Adaptor2d_OffsetCurve aOC(BaseCurve, Offset) --> Adaptor2d_OffsetCurve aOC(BaseCurve, -Offset)
|
||||
|
||||
subsection upgrade_750_ProgressIndicator Change of Message_ProgressIndicator
|
||||
@subsection upgrade_750_ProgressIndicator Change of progress indication API
|
||||
|
||||
The progress indication mechanism has been revised to eliminate its weak points in previous design (leading to ambiguity and unprotected from an error-prone behavior).
|
||||
Redesign also allows using progress indicator in multi-threaded algorithms in more straight-forward way with minimal overhead.
|
||||
Note, however, that multi-threaded algorithm should pre-allocate per-thread progress scopes in advance to ensure thread-safety - check new classes API for details.
|
||||
The progress indication mechanism has been revised to eliminate its weak points in
|
||||
previous design (leading to implementation mistakes).
|
||||
Redesign also allows using progress indicator in multi-threaded algorithms
|
||||
in more straight-forward way with minimal overhead.
|
||||
Note however, that multi-threaded algorithm should pre-allocate per-task
|
||||
progress ranges in advance to ensure thread-safety -
|
||||
see examples in documentation of class Message_ProgressScope for details.
|
||||
|
||||
Classes Message_ProgressSentry and Message_ProgressScale have been removed.
|
||||
New classes Message_ProgressScope and Messge_ProgressRange replace them and should be used as main API classes to organize progress indication in the algorithms.
|
||||
Instances of the class Message_ProgressRange are used to pass the progress capability to nested levels of the algorithm
|
||||
and an instance of the class Message_ProgressScope is to be created (preferably as local variable) to manage progress at each level of the algorithm.
|
||||
New classes Message_ProgressScope and Message_ProgressRange should be used as main
|
||||
API classes to organize progress indication in the algorithms.
|
||||
Instances of the class Message_ProgressRange are used to pass the progress capability to
|
||||
nested levels of the algorithm, and an instance of the class Message_ProgressScope is to
|
||||
be created (preferably as local variable) to manage progress at each level of the algorithm.
|
||||
The instance of Message_ProgressIndicator is not passed anymore to sub-algorithms.
|
||||
See documentation of the class Message_ProgressScope for more details and examples.
|
||||
|
||||
Methods to deal with progress scopes and to advance progress are removed from class Message_ProgressIndicator; now it only provides interface to the application-level progress indicator.
|
||||
Virtual method Message_ProgressIndicator::Show() has changed its signature and should be updated accordingly in descendants of Message_ProgressIndicator.
|
||||
The scope passed as argument to this method can be used to obtain information on context of the current process (instead of calling method GetScope() in previous implementation).
|
||||
Methods Show(), UserBreak(), and Reset() are made protected in class Message_ProgressIndicator; method More() of Message_ProgressScope should be used to know if the cancel event has come.
|
||||
See documentation of the class Message_ProgressIndicator for more details and implementation of Draw_ProgressIndicator for an example.
|
||||
Methods to deal with progress scopes and to advance progress are removed from class
|
||||
Message_ProgressIndicator; now it only provides interface to the application-level progress indicator.
|
||||
Virtual method Message_ProgressIndicator::Show() has changed its signature and should be
|
||||
updated accordingly in descendants of Message_ProgressIndicator.
|
||||
The scope passed as argument to this method can be used to obtain information on context
|
||||
of the current process (instead of calling method GetScope() in previous implementation).
|
||||
Methods Show(), UserBreak(), and Reset() are made protected in class Message_ProgressIndicator;
|
||||
methods More() or UserBreak() of classes Message_ProgressScope or Message_ProgressRange should
|
||||
be used to know if the cancel event has come.
|
||||
See documentation of the class Message_ProgressIndicator for more details and implementation
|
||||
of Draw_ProgressIndicator for an example.
|
||||
|
||||
Lets take a look onto typical algorithm using an old API:
|
||||
Let's take a look onto typical algorithm using an old API:
|
||||
@code
|
||||
class MyAlgo
|
||||
{
|
||||
@ -1967,7 +1979,10 @@ public:
|
||||
{
|
||||
Message_ProgressSentry aPSentry1 (theProgress, "Stage 1", 0, 153, 1);
|
||||
for (int anIter = 0; anIter < 153; ++anIter, aPSentry1.Next())
|
||||
{ if (!aPSentry1.More()) { return false; } }
|
||||
{
|
||||
if (!aPSentry1.More()) { return false; }
|
||||
// do some job here...
|
||||
}
|
||||
}
|
||||
aPSentry.Next();
|
||||
{
|
||||
@ -1982,9 +1997,9 @@ private:
|
||||
//! Nested sub-algorithm taking Progress Indicator.
|
||||
bool perform2 (const Handle(Message_ProgressIndicator)& theProgress)
|
||||
{
|
||||
Message_ProgressSentry aPSentry2 (theProgress, "Stage 2", 0, 561, 1);
|
||||
for (int anIter = 0; anIter < 561 && aPSentry2.More(); ++anIter, aPSentry2.Next()) {}
|
||||
return aPSentry2.More();
|
||||
Message_ProgressSentry aPSentry2 (theProgress, "Stage 2", 0, 100, 1);
|
||||
for (int anIter = 0; anIter < 100 && aPSentry2.More(); ++anIter, aPSentry2.Next()) {}
|
||||
return !aPSentry2.UserBreak();
|
||||
}
|
||||
};
|
||||
|
||||
@ -1995,19 +2010,25 @@ anAlgo.Perform ("FileName", aProgress);
|
||||
@endcode
|
||||
|
||||
The following guidance can be used to update such code:
|
||||
- Replace `const Handle(Message_ProgressIndicator)&` with `const Message_ProgressRange&`.
|
||||
- Replace `const Handle(Message_ProgressIndicator)&` with `const Message_ProgressRange&`
|
||||
in arguments of the methods that support progress indication.
|
||||
Message_ProgressIndicator object should be now created only at place where application starts algorithms.
|
||||
- Replace `Message_ProgressSentry` with `Message_ProgressScope`.
|
||||
Take note that Message_ProgressScope has smaller number of arguments (no "minimal value").
|
||||
In other aspects, Message_ProgressScope mimics an iterator-style interface (with methods More() and Next())
|
||||
close to the old Message_ProgressSentry (pay attention to extra functionality of Message_ProgressScope::Next() method below).
|
||||
- Each Message_ProgressScope should take the next Range to fill in.
|
||||
Within old API, Message_ProgressSentry received the root Progress Indicator object and implicitly split it into ranges using error-prone logic.
|
||||
Message_ProgressScope in new API takes Message_ProgressRange, which should be created from the Range of the parent Scope using value returned by Message_ProgressScope::Next() method.
|
||||
Don't use the same Range passed to the algorithm for all sub-Scopes like it was possible in old API.
|
||||
- Check user abortion state using Message_ProgressScope::UserBreak() method;
|
||||
Message_ProgressRange is a temporary object with the only purpose to create a new Message_ProgressScope,
|
||||
and Message_ProgressIndicator should be never passed directly to algorithms.
|
||||
Take note that Message_ProgressScope has less arguments (no "minimal value").
|
||||
In other aspects, Message_ProgressScope mimics an iterator-style interface
|
||||
(with methods More() and Next()) close to the old Message_ProgressSentry (pay attention
|
||||
to extra functionality of Message_ProgressScope::Next() method below).
|
||||
Note that method Message_ProgressScope::Close() is equivalent of the method
|
||||
Relieve() of Message_ProgressSentry in previous version.
|
||||
Class Message_ProgressSentry is still defined (marked as deprecated) providing
|
||||
API more close to old one, and can be still used to reduce porting efforts.
|
||||
- Each Message_ProgressScope should take the next Range object to work with.
|
||||
Within old API, Message_ProgressSentry received the root Progress Indicator
|
||||
object which mantained the sequence of ranges internally.
|
||||
Message_ProgressScope in new API takes Message_ProgressRange, which should be
|
||||
returned by Message_ProgressScope::Next() method of the parent scope.
|
||||
Do not use the same Range passed to the algorithm for all sub-Scopes like
|
||||
it was possible in old API; each range object may be used only once.
|
||||
|
||||
Take a look onto ported code and compare with code above to see differences:
|
||||
|
||||
@ -2023,7 +2044,10 @@ public:
|
||||
{
|
||||
Message_ProgressScope aPSentry1 (aPSentry.Next(), "Stage 1", 153);
|
||||
for (int anIter = 0; anIter < 153; ++anIter, aPSentry1.Next())
|
||||
{ if (!aPSentry1.More()) { return false; }; }
|
||||
{
|
||||
if (!aPSentry1.More()) { return false; };
|
||||
// do some job here...
|
||||
}
|
||||
}
|
||||
{
|
||||
perform2 (aPSentry.Next());
|
||||
@ -2035,9 +2059,9 @@ public:
|
||||
//! Nested sub-algorithm taking Progress sub-Range.
|
||||
bool perform2 (const Message_ProgressRange& theProgress)
|
||||
{
|
||||
Message_ProgressScope aPSentry2 (theProgress, "Stage 2", 561);
|
||||
for (int anIter = 0; anIter < 561 && aPSentry2.More(); ++anIter, aPSentry2.Next()) {}
|
||||
return aPSentry2.More();
|
||||
Message_ProgressScope aPSentry2 (theProgress, "Stage 2", 100);
|
||||
for (int anIter = 0; anIter < 100 && aPSentry2.More(); ++anIter, aPSentry2.Next()) {}
|
||||
return !aPSentry2.UserBreak();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -202,7 +202,7 @@ Standard_Boolean Draw_ProgressIndicator::UserBreak()
|
||||
{
|
||||
OSD::ControlBreak();
|
||||
}
|
||||
catch (OSD_Exception_CTRL_BREAK)
|
||||
catch (const OSD_Exception_CTRL_BREAK&)
|
||||
{
|
||||
myBreak = Standard_True;
|
||||
}
|
||||
|
@ -99,12 +99,12 @@ protected:
|
||||
//! Show() should return as soon as possible to reduce thread contention
|
||||
//! in multithreaded algorithms.
|
||||
//!
|
||||
//! It is recommended to update (redraw, output etc.) only if progress advanced
|
||||
//! by at least 1% from previous update.
|
||||
//! It is recommended to update (redraw, output etc.) only if progress is
|
||||
//! advanced by at least 1% from previous update.
|
||||
//!
|
||||
//! Flag isForce is intended for forcing update in case if it is
|
||||
//! optimized; all calls to it from inside the core mechanism are
|
||||
//! done with this flag equal to False.
|
||||
//! Flag isForce is intended for forcing update in case if it is required
|
||||
//! at particular step of the algorithm; all calls to it from inside the core
|
||||
//! mechanism (Message_Progress... classes) are done with this flag equal to False.
|
||||
//!
|
||||
//! The parameter theScope is the current scope being advanced;
|
||||
//! it can be used to show the names and ranges of the on-going scope and
|
||||
@ -120,7 +120,7 @@ public:
|
||||
//!@name Auxiliary methods
|
||||
|
||||
//! Returns total progress position ranged from 0 to 1.
|
||||
//! Should not be called concurrently while the progress is advancing
|
||||
//! Should not be called concurrently while the progress is advancing,
|
||||
//! except from implementation of method Show().
|
||||
Standard_Real GetPosition() const
|
||||
{
|
||||
|
@ -32,21 +32,22 @@ class Message_ProgressScope;
|
||||
//! A range object can be copied, the responsibility for progress advancement is
|
||||
//! then taken by the copy.
|
||||
//! The same range object may be used (either copied or used to create scope) only once.
|
||||
//! Any consequenct attempts to use range will give no result on the progress;
|
||||
//! Any consequent attempts to use range will give no result on the progress;
|
||||
//! in debug mode, an assert message will be generated.
|
||||
//!
|
||||
//! @sa Message_ProgressScope for more details
|
||||
class Message_ProgressRange
|
||||
{
|
||||
public:
|
||||
//! Constructor of the range
|
||||
//! Constructor of the empty range
|
||||
Message_ProgressRange()
|
||||
: myParentScope (0), myDelta (0), myWasUsed (false)
|
||||
: myParentScope (0), myStart(0.), myDelta (0.), myWasUsed (false)
|
||||
{}
|
||||
|
||||
//! Copy constructor disarms the source.
|
||||
//! Copy constructor disarms the source
|
||||
Message_ProgressRange (const Message_ProgressRange& theOther)
|
||||
: myParentScope (theOther.myParentScope),
|
||||
myStart (theOther.myStart),
|
||||
myDelta (theOther.myDelta),
|
||||
myWasUsed (theOther.myWasUsed)
|
||||
{
|
||||
@ -54,10 +55,11 @@ public:
|
||||
theOther.myWasUsed = true;
|
||||
}
|
||||
|
||||
//! Copy assignment disarms the source.
|
||||
//! Copy assignment disarms the source
|
||||
Message_ProgressRange& operator=(const Message_ProgressRange& theOther)
|
||||
{
|
||||
myParentScope = theOther.myParentScope;
|
||||
myStart = theOther.myStart;
|
||||
myDelta = theOther.myDelta;
|
||||
myWasUsed = theOther.myWasUsed;
|
||||
theOther.myWasUsed = true;
|
||||
@ -87,15 +89,19 @@ public:
|
||||
|
||||
private:
|
||||
//! Constructor is private
|
||||
Message_ProgressRange (const Message_ProgressScope& theParent, Standard_Real theDelta)
|
||||
Message_ProgressRange (const Message_ProgressScope& theParent,
|
||||
Standard_Real theStart, Standard_Real theDelta)
|
||||
: myParentScope (&theParent),
|
||||
myStart (theStart),
|
||||
myDelta (theDelta),
|
||||
myWasUsed (false)
|
||||
{}
|
||||
|
||||
private:
|
||||
const Message_ProgressScope* myParentScope; //!< Pointer to parent scope
|
||||
Standard_Real myDelta; //!< Step of incrementation
|
||||
Standard_Real myStart; //!< Start point on the global scale
|
||||
Standard_Real myDelta; //!< Step of incrementation on the global scale
|
||||
|
||||
mutable Standard_Boolean myWasUsed; //!< Flag indicating that this range
|
||||
//! was used to create a new scope
|
||||
|
||||
|
@ -34,29 +34,48 @@ class Message_ProgressIndicator;
|
||||
//! On every level (sub-operation) in hierarchy of operations
|
||||
//! the local instance of the Message_ProgressScope class is created.
|
||||
//! It takes a part of the upper-level scope (via Message_ProgressRange) and provides
|
||||
//! a way to consider this part as independent scale with locally defined range.
|
||||
//! a way to consider this part as independent scale with locally defined range.
|
||||
//!
|
||||
//! The position on the local scale may be advanced using the method Next(),
|
||||
//! which allows iteration-like advancement. This method can take argument to
|
||||
//! advance on the needed value. And, this method returns ProgressRange object
|
||||
//! that takes responsibility of making the specified step at its destruction.
|
||||
//! The ProgressRange can be used to create a new progress sub-scope.
|
||||
//! advance by the specified value (with default step equal to 1).
|
||||
//! This method returns Message_ProgressRange object that takes responsibility
|
||||
//! of making the specified step, either directly at its destruction or by
|
||||
//! delegating this task to another sub-scope created from that range object.
|
||||
//!
|
||||
//! It is important that sub-scope must have life time less than
|
||||
//! the life time of its parent scope that provided the range.
|
||||
//! The usage pattern is to create scope objects as local variables in the
|
||||
//! functions that do the job, and pass range objects returned by Next() to
|
||||
//! the functions of the lower level, to allow them creating their own scopes.
|
||||
//!
|
||||
//! The scope has a name that can be used in visualization of the progress.
|
||||
//! It can be null. Note that the string is not copied, just pointer is stored.
|
||||
//! So, the pointer must point to the string with life time
|
||||
//! greater than that of the scope object.
|
||||
//! It can be null. Note that when C string literal is used as a name, then its
|
||||
//! value is not copied, just pointer is stored. In other variants (char pointer
|
||||
//! or a string class) the string is copied, which is additional overhead.
|
||||
//!
|
||||
//! In multithreaded programs, for each task running concurrently it is recommended
|
||||
//! to create a separate progress scope. The same instance of the progress scope
|
||||
//! must not be used concurrently from different threads.
|
||||
//! The same instance of the progress scope! must not be used concurrently from different threads.
|
||||
//! For the algorithm running its tasks in parallel threads, a common scope is
|
||||
//! created before the parallel execution, and the range objects produced by method
|
||||
//! Next() are used to initialise the data pertinent to each task.
|
||||
//! Then the progress is advanced within each task using its own range object.
|
||||
//! See example below.
|
||||
//!
|
||||
//! Note that while a range of the scope is specified using Standard_Real
|
||||
//! (double) parameter, it is expected to be a positive integer value.
|
||||
//! If the range is not an integer, method Next() shall be called with
|
||||
//! explicit step argument, and the rounded value returned by method Value()
|
||||
//! may be not coherent with the step and range.
|
||||
//!
|
||||
//! A scope can be created with option "infinite". This is useful when
|
||||
//! the number of steps is not known by the time of the scope creation.
|
||||
//! In this case the progress will be advanced logarithmically, approaching
|
||||
//! the end of the scope at infinite number of steps. The parameter Max
|
||||
//! for infinite scope indicates number of steps corresponding to mid-range.
|
||||
//!
|
||||
//! A progress scope created with empty constructor is not connected to any
|
||||
//! progress indicator, and passing the range created on it to any algorithm
|
||||
//! allows it executing safely without progress indication.
|
||||
//! allows it executing safely without actual progress indication.
|
||||
//!
|
||||
//! Example of preparation of progress indicator:
|
||||
//!
|
||||
@ -132,12 +151,11 @@ class Message_ProgressIndicator;
|
||||
//! {
|
||||
//! void operator() (Task& theTask) const
|
||||
//! {
|
||||
//! // Note: it is essential that this method is executed only once
|
||||
//! // for the same Task object
|
||||
//! Message_ProgressScope aPS (theTask.Range, "Processing task", 1);
|
||||
//! if (aPS.More())
|
||||
//! // Note: it is essential that this method is executed only once for the same Task object
|
||||
//! Message_ProgressScope aPS (theTask.Range, NULL, theTask.Data.NbItems);
|
||||
//! for (Standard_Integer i = 0; i < theTask.Data.NbSteps && aPS.More(); i++)
|
||||
//! {
|
||||
//! // ... process data
|
||||
//! do_job (theTask.Data.Item[i], aPS.Next());
|
||||
//! }
|
||||
//! }
|
||||
//! };
|
||||
@ -153,6 +171,24 @@ class Message_ProgressIndicator;
|
||||
//! OSD_Parallel::ForEach (aTasks.begin(), aTasks.end(), Functor());
|
||||
//! }
|
||||
//! @endcode
|
||||
//!
|
||||
//! For lightweight algorithms that do not need advancing the progress
|
||||
//! within individual tasks the code can be simplified to avoid inner scopes:
|
||||
//!
|
||||
//! @code
|
||||
//! struct Functor
|
||||
//! {
|
||||
//! void operator() (Task& theTask) const
|
||||
//! {
|
||||
//! if (theTask.Range.More())
|
||||
//! {
|
||||
//! do_job (theTask.Data);
|
||||
//! // advance the progress
|
||||
//! theTask.Range.Close();
|
||||
//! }
|
||||
//! }
|
||||
//! };
|
||||
//! @endcode
|
||||
class Message_ProgressScope
|
||||
{
|
||||
public:
|
||||
@ -165,7 +201,10 @@ public: //! @name Preparation methods
|
||||
: myProgress (0),
|
||||
myParent (0),
|
||||
myName (0),
|
||||
myPortion (1.), myMax (1.), myValue (0.),
|
||||
myStart (0.),
|
||||
myPortion (1.),
|
||||
myMax (1.),
|
||||
myValue (0.),
|
||||
myIsActive (false),
|
||||
myIsOwnName (false),
|
||||
myIsInfinite (false)
|
||||
@ -302,12 +341,16 @@ public: //! @name Auxiliary methods to use in ProgressIndicator
|
||||
}
|
||||
|
||||
//! Returns the current value of progress in this scope.
|
||||
//! If this scope is being advanced by sub-scoping, that value is
|
||||
//! computed by mapping current global progress into this scope range.
|
||||
Standard_Real Value() const
|
||||
{
|
||||
return myIsActive ? myValue : myMax;
|
||||
}
|
||||
//!
|
||||
//! The value is computed by mapping current global progress into
|
||||
//! this scope range; the result is rounded up to integer.
|
||||
//! Note that if MaxValue() is not an integer, Value() can be
|
||||
//! greater than MaxValue() due to that rounding.
|
||||
//!
|
||||
//! This method should not be called concurrently while the progress
|
||||
//! is advancing, except from implementation of method Show() in
|
||||
//! descendant of Message_ProgressIndicator.
|
||||
Standard_Real Value() const;
|
||||
|
||||
//! Returns the infinite flag
|
||||
Standard_Boolean IsInfinite() const
|
||||
@ -326,7 +369,7 @@ public: //! @name Destruction, allocation
|
||||
//! Destructor - closes the scope and adds its scale to the total progress
|
||||
~Message_ProgressScope()
|
||||
{
|
||||
Relieve();
|
||||
Close();
|
||||
if (myIsOwnName)
|
||||
{
|
||||
Standard::Free (myName);
|
||||
@ -335,9 +378,9 @@ public: //! @name Destruction, allocation
|
||||
}
|
||||
}
|
||||
|
||||
//! Closes the scope and adds its scale to the total progress.
|
||||
//! Relieved scope should not be used.
|
||||
void Relieve();
|
||||
//! Closes the scope and advances the progress to its end.
|
||||
//! Closed scope should not be used.
|
||||
void Close();
|
||||
|
||||
DEFINE_STANDARD_ALLOC
|
||||
|
||||
@ -347,12 +390,10 @@ private: //! @name Internal methods
|
||||
//! Called only by Message_ProgressIndicator constructor.
|
||||
Message_ProgressScope (Message_ProgressIndicator* theProgress);
|
||||
|
||||
//! Convert value from this scale to global one
|
||||
//! Convert value from this scope to global scale, but disregarding
|
||||
//! start position of the scope, in the range [0, myPortion]
|
||||
Standard_Real localToGlobal(const Standard_Real theVal) const;
|
||||
|
||||
//! Convert value from global scale to this one
|
||||
Standard_Real globalToLocal(const Standard_Real theVal) const;
|
||||
|
||||
private:
|
||||
//! Copy constructor is prohibited
|
||||
Message_ProgressScope (const Message_ProgressScope& theOther);
|
||||
@ -366,7 +407,9 @@ private:
|
||||
const Message_ProgressScope* myParent; //!< Pointer to parent scope
|
||||
Standard_CString myName; //!< Name of the operation being done in this scope, or null
|
||||
|
||||
Standard_Real myPortion; //!< The portion of the global scale covered by this scope (from 0 to 1)
|
||||
Standard_Real myStart; //!< Start position on the global scale [0, 1]
|
||||
Standard_Real myPortion; //!< The portion of the global scale covered by this scope [0, 1]
|
||||
|
||||
Standard_Real myMax; //!< Maximal value of progress in this scope
|
||||
Standard_Real myValue; //!< Current position advanced within this scope [0, Max]
|
||||
|
||||
@ -389,6 +432,7 @@ inline Message_ProgressScope::Message_ProgressScope (Message_ProgressIndicator*
|
||||
: myProgress(theProgress),
|
||||
myParent(0),
|
||||
myName(0),
|
||||
myStart(0.),
|
||||
myPortion(1.),
|
||||
myMax(1.),
|
||||
myValue(0.),
|
||||
@ -409,6 +453,7 @@ inline Message_ProgressScope::Message_ProgressScope (const Message_ProgressRange
|
||||
: myProgress (theRange.myParentScope != NULL ? theRange.myParentScope->myProgress : NULL),
|
||||
myParent (theRange.myParentScope),
|
||||
myName (NULL),
|
||||
myStart (theRange.myStart),
|
||||
myPortion (theRange.myDelta),
|
||||
myMax (Max (1.e-6, theMax)), // protection against zero range
|
||||
myValue (0.),
|
||||
@ -433,6 +478,7 @@ Message_ProgressScope::Message_ProgressScope (const Message_ProgressRange& theRa
|
||||
: myProgress (theRange.myParentScope != NULL ? theRange.myParentScope->myProgress : NULL),
|
||||
myParent (theRange.myParentScope),
|
||||
myName (theName),
|
||||
myStart (theRange.myStart),
|
||||
myPortion (theRange.myDelta),
|
||||
myMax (Max (1.e-6, theMax)), // protection against zero range
|
||||
myValue (0.),
|
||||
@ -455,6 +501,7 @@ inline Message_ProgressScope::Message_ProgressScope (const Message_ProgressRange
|
||||
: myProgress (theRange.myParentScope != NULL ? theRange.myParentScope->myProgress : NULL),
|
||||
myParent (theRange.myParentScope),
|
||||
myName (NULL),
|
||||
myStart (theRange.myStart),
|
||||
myPortion (theRange.myDelta),
|
||||
myMax (Max (1.e-6, theMax)), // protection against zero range
|
||||
myValue (0.),
|
||||
@ -467,10 +514,10 @@ inline Message_ProgressScope::Message_ProgressScope (const Message_ProgressRange
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : Relieve
|
||||
//function : Close
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
inline void Message_ProgressScope::Relieve()
|
||||
inline void Message_ProgressScope::Close()
|
||||
{
|
||||
if (!myIsActive)
|
||||
{
|
||||
@ -506,17 +553,14 @@ inline Standard_Boolean Message_ProgressScope::UserBreak() const
|
||||
//=======================================================================
|
||||
inline Message_ProgressRange Message_ProgressScope::Next (Standard_Real theStep)
|
||||
{
|
||||
if (myIsActive)
|
||||
if (myIsActive && theStep > 0.)
|
||||
{
|
||||
if (theStep > 0.)
|
||||
Standard_Real aCurr = localToGlobal(myValue);
|
||||
Standard_Real aNext = localToGlobal(myValue += theStep);
|
||||
Standard_Real aDelta = aNext - aCurr;
|
||||
if (aDelta > 0.)
|
||||
{
|
||||
Standard_Real aCurr = localToGlobal (myValue);
|
||||
Standard_Real aNext = localToGlobal (myValue += theStep);
|
||||
Standard_Real aDelta = aNext - aCurr;
|
||||
if (aDelta > 0.)
|
||||
{
|
||||
return Message_ProgressRange (*this, aDelta);
|
||||
}
|
||||
return Message_ProgressRange(*this, myStart + aCurr, aDelta);
|
||||
}
|
||||
}
|
||||
return Message_ProgressRange();
|
||||
@ -557,23 +601,34 @@ inline Standard_Real Message_ProgressScope::localToGlobal (const Standard_Real t
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : globalToLocal
|
||||
//function : Value
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
|
||||
inline Standard_Real Message_ProgressScope::globalToLocal (const Standard_Real theVal) const
|
||||
inline Standard_Real Message_ProgressScope::Value () const
|
||||
{
|
||||
if (!myIsActive)
|
||||
{
|
||||
return myIsInfinite ? Precision::Infinite() : myMax;
|
||||
}
|
||||
|
||||
// get current progress on the global scale counted
|
||||
// from the start of this scope
|
||||
Standard_Real aVal = myProgress->GetPosition() - myStart;
|
||||
|
||||
// if progress has not reached yet the start of this scope, return 0
|
||||
if (aVal <= 0.)
|
||||
return 0.;
|
||||
|
||||
// if at end of the scope (or behind), report the maximum
|
||||
Standard_Real aDist = myPortion - theVal;
|
||||
Standard_Real aDist = myPortion - aVal;
|
||||
if (aDist <= Precision::Confusion())
|
||||
return myIsInfinite ? Precision::Infinite() : myMax;
|
||||
|
||||
if (!myIsInfinite)
|
||||
return myMax * theVal / myPortion;
|
||||
|
||||
// Standard_Real x = log (theVal / aDist); // exponent
|
||||
Standard_Real x = theVal / aDist; // hyperbola
|
||||
return x * myMax;
|
||||
// map the value to the range of this scope [0, Max],
|
||||
// rounding up to integer, with small correction applied
|
||||
// to avoid rounding errors
|
||||
return std::ceil (myMax * aVal / (myIsInfinite ? aDist : myPortion) - Precision::Confusion());
|
||||
}
|
||||
|
||||
#endif // _Message_ProgressScope_HeaderFile
|
||||
|
@ -38,6 +38,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
//! Method Relieve() was replaced by Close() in Message_ProgressScope
|
||||
void Relieve () { Close(); }
|
||||
|
||||
private:
|
||||
//! Message_ProgressRange should be passed to constructor instead of Message_ProgressIndicator.
|
||||
Message_ProgressSentry (const Handle(Message_ProgressIndicator)& theProgress,
|
||||
|
@ -4843,12 +4843,12 @@ namespace
|
||||
{
|
||||
void operator()(Task& theTask) const
|
||||
{
|
||||
Message_ProgressScope aPS(theTask.Range, NULL, 1);
|
||||
if (aPS.More())
|
||||
if (theTask.Range.More())
|
||||
{
|
||||
if (theTask.Mat1.RowNumber() > 1)
|
||||
theTask.Mat3 = theTask.Mat1 * theTask.Mat2;
|
||||
}
|
||||
theTask.Range.Close();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user