// Created on: 2002-02-20 // Created by: Andrey BETENEV // Copyright (c) 2002-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. #ifndef _Message_ProgressIndicator_HeaderFile #define _Message_ProgressIndicator_HeaderFile #include "Standard_Handle.hxx" #include "Standard_Transient.hxx" #include "Standard_Type.hxx" #include class Message_ProgressRange; class Message_ProgressScope; //! Defines abstract interface from program to the user. //! This includes progress indication and user break mechanisms. //! //! The progress indicator controls the progress scale with range from 0 to 1. //! //! Method Start() should be called once, at the top level of the call stack, //! to reset progress indicator and get access to the root range: //! //! @code{.cpp} //! occ::handle aProgress = ...; //! anAlgorithm.Perform (aProgress->Start()); //! @endcode //! //! To advance the progress indicator in the algorithm, //! use the class Message_ProgressScope that provides iterator-like //! interface for incrementing progress; see documentation of that //! class for details. //! The object of class Message_ProgressRange will automatically advance //! the indicator if it is not passed to any Message_ProgressScope. //! //! The progress indicator supports concurrent processing and //! can be used in multithreaded applications. //! //! The derived class should be created to connect this interface to //! actual implementation of progress indicator, to take care of visualization //! of the progress (e.g. show total position at the graphical bar, //! print scopes in text mode, or else), and for implementation //! of user break mechanism (if necessary). //! //! See details in documentation of methods Show() and UserBreak(). class Message_ProgressIndicator : public Standard_Transient { DEFINE_STANDARD_RTTIEXT(Message_ProgressIndicator, Standard_Transient) public: //!@name Initialization of progress indication //! Resets the indicator to zero, calls Reset(), and returns the range. //! This range refers to the scope that has no name and is initialized //! with max value 1 and step 1. //! Use this method to get the top level range for progress indication. Standard_EXPORT Message_ProgressRange Start(); //! If argument is non-null handle, returns theProgress->Start(). //! Otherwise, returns dummy range that can be safely used in the algorithms //! but not bound to progress indicator. Standard_EXPORT static Message_ProgressRange Start( const occ::handle& theProgress); protected: //!@name Virtual methods to be defined by descendant. //! Should return True if user has sent a break signal. //! //! This method can be called concurrently, thus implementation should //! be thread-safe. It should not call Show() or Position() to //! avoid possible data races. The method should return as soon //! as possible to avoid delaying the calling algorithm. //! //! Default implementation returns False. virtual bool UserBreak() { return false; } //! Virtual method to be defined by descendant. //! Should update presentation of the progress indicator. //! //! It is called whenever progress position is changed. //! Calls to this method from progress indicator are protected by mutex so that //! it is never called concurrently for the same progress indicator instance. //! 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 is //! advanced by at least 1% from previous update. //! //! 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 //! its parents, providing more visibility of the current stage of the process. virtual void Show(const Message_ProgressScope& theScope, const bool isForce) = 0; //! Call-back method called by Start(), can be redefined by descendants //! if some actions are needed when the indicator is restarted. virtual void Reset() {} public: //!@name Auxiliary methods //! Returns total progress position ranged from 0 to 1. //! Should not be called concurrently while the progress is advancing, //! except from implementation of method Show(). double GetPosition() const { return myPosition; } //! Destructor Standard_EXPORT ~Message_ProgressIndicator() override; protected: //! Constructor Standard_EXPORT Message_ProgressIndicator(); private: //! Increment the progress value by the specified step, //! then calls Show() to update presentation. //! The parameter theScope is reference to the caller object; //! it is passed to Show() where can be used to track context of the process. void Increment(const double theStep, const Message_ProgressScope& theScope); private: double myPosition; //!< Total progress position ranged from 0 to 1 std::mutex myMutex; //!< Protection of myPosition from concurrent increment Message_ProgressScope* myRootScope; //!< The root progress scope private: friend class Message_ProgressScope; //!< Friend: can call Increment() friend class Message_ProgressRange; //!< Friend: can call Increment() }; #include "Message_ProgressScope.hxx" //================================================================================================= inline void Message_ProgressIndicator::Increment(const double theStep, const Message_ProgressScope& theScope) { // protect incrementation by mutex to avoid problems in multithreaded scenarios std::lock_guard aLock(myMutex); myPosition = (std::min)(myPosition + theStep, 1.); // show progress indicator; note that this call is protected by // the same mutex to avoid concurrency and ensure that this call // to Show() will see the position exactly as it was just set above Show(theScope, false); } #endif // _Message_ProgressIndicator_HeaderFile