0025748: Parallel version of progress indicator
[occt.git] / src / Message / Message_ProgressIndicator.hxx
1 // Created on: 2002-02-20
2 // Created by: Andrey BETENEV
3 // Copyright (c) 2002-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #ifndef _Message_ProgressIndicator_HeaderFile
17 #define _Message_ProgressIndicator_HeaderFile
18
19 #include <Standard_TypeDef.hxx>
20 #include <Standard_Mutex.hxx>
21 #include <Standard_Handle.hxx>
22
23 DEFINE_STANDARD_HANDLE(Message_ProgressIndicator, Standard_Transient)
24
25 class Message_ProgressRange;
26 class Message_ProgressScope;
27
28 //! Defines abstract interface from program to the user.
29 //! This includes progress indication and user break mechanisms.
30 //!
31 //! The progress indicator controls the progress scale with range from 0 to 1.
32 //! 
33 //! Method Start() should be called once, at the top level of the call stack,
34 //! to reset progress indicator and get access to the root range:
35 //!
36 //! @code{.cpp}
37 //! Handle(Message_ProgressIndicator) aProgress = ...;
38 //! anAlgorithm.Perform (aProgress->Start());
39 //! @endcode
40 //!
41 //! To advance the progress indicator in the algorithm,
42 //! use the class Message_ProgressScope that provides iterator-like
43 //! interface for incrementing progress; see documentation of that
44 //! class for details.
45 //! The object of class Message_ProgressRange will automatically advance 
46 //! the indicator if it is not passed to any Message_ProgressScope.
47 //!
48 //! The progress indicator supports concurrent processing and 
49 //! can be used in multithreaded applications.
50 //!
51 //! The derived class should be created to connect this interface to 
52 //! actual implementation of progress indicator, to take care of visualization
53 //! of the progress (e.g. show total position at the graphical bar,
54 //! print scopes in text mode, or else), and for implementation
55 //! of user break mechanism (if necessary).
56 //!
57 //! See details in documentation of methods Show() and UserBreak().
58
59 class Message_ProgressIndicator : public Standard_Transient
60 {
61   DEFINE_STANDARD_RTTIEXT(Message_ProgressIndicator, Standard_Transient)
62 public:
63   //!@name Initialization of progress indication
64
65   //! Resets the indicator to zero, calls Reset(), and returns the range.
66   //! This range refers to the scope that has no name and is initialized
67   //! with max value 1 and step 1.
68   //! Use this method to get the top level range for progress indication.
69   Standard_EXPORT Message_ProgressRange Start();
70
71   //! If argument is non-null handle, returns theProgress->Start().
72   //! Otherwise, returns dummy range that can be safely used in the algorithms
73   //! but not bound to progress indicator.
74   Standard_EXPORT static Message_ProgressRange Start
75                       (const Handle(Message_ProgressIndicator)& theProgress);
76
77 protected:
78   //!@name Virtual methods to be defined by descendant.
79
80   //! Should return True if user has sent a break signal.
81   //!
82   //! This method can be called concurrently, thus implementation should
83   //! be thread-safe. It should not call Show() or Position() to
84   //! avoid possible data races. The method should return as soon
85   //! as possible to avoid delaying the calling algorithm.
86   //!
87   //! Default implementation returns False.
88   virtual Standard_Boolean UserBreak()
89   {
90     return Standard_False;
91   }
92
93   //! Virtual method to be defined by descendant.
94   //! Should update presentation of the progress indicator.
95   //!
96   //! It is called whenever progress position is changed.
97   //! Calls to this method from progress indicator are protected by mutex so that
98   //! it is never called concurrently for the same progress indicator instance.
99   //! Show() should return as soon as possible to reduce thread contention
100   //! in multithreaded algorithms.
101   //!
102   //! It is recommended to update (redraw, output etc.) only if progress advanced
103   //! by at least 1% from previous update.
104   //!
105   //! Flag isForce is intended for forcing update in case if it is
106   //! optimized; all calls to it from inside the core mechanism are
107   //! done with this flag equal to False.
108   //!
109   //! The parameter theScope is the current scope being advanced;
110   //! it can be used to show the names and ranges of the on-going scope and
111   //! its parents, providing more visibility of the current stage of the process.
112   virtual void Show (const Message_ProgressScope& theScope, 
113                      const Standard_Boolean isForce) = 0;
114
115   //! Call-back method called by Start(), can be redefined by descendants
116   //! if some actions are needed when the indicator is restarted.
117   virtual void Reset() {}
118   
119 public:
120   //!@name Auxiliary methods
121
122   //! Returns total progress position ranged from 0 to 1.
123   //! Should not be called concurrently while the progress is advancing
124   //! except from implementation of method Show().
125   Standard_Real GetPosition() const
126   {
127     return myPosition;
128   }
129
130   //! Destructor
131   Standard_EXPORT ~Message_ProgressIndicator();
132
133 protected:
134   
135   //! Constructor
136   Standard_EXPORT Message_ProgressIndicator();
137
138 private:
139
140   //! Increment the progress value by the specified step, 
141   //! then calls Show() to update presentation.
142   //! The parameter theScope is reference to the caller object;
143   //! it is passed to Show() where can be used to track context of the process.
144   void Increment (const Standard_Real theStep, const Message_ProgressScope& theScope);
145
146 private:
147
148   Standard_Real myPosition;            //!< Total progress position ranged from 0 to 1
149   Standard_Mutex myMutex;              //!< Protection of myPosition from concurrent increment
150   Message_ProgressScope* myRootScope;  //!< The root progress scope
151
152 private:
153   friend class Message_ProgressScope;  //!< Friend: can call Increment()
154   friend class Message_ProgressRange;  //!< Friend: can call Increment()
155 };
156
157 #include <Message_ProgressScope.hxx>
158
159 //=======================================================================
160 //function : Increment
161 //purpose  :
162 //=======================================================================
163 inline void Message_ProgressIndicator::Increment(const Standard_Real theStep,
164                                                  const Message_ProgressScope& theScope)
165 {
166   // protect incrementation by mutex to avoid problems in multithreaded scenarios
167   Standard_Mutex::Sentry aSentry(myMutex);
168
169   myPosition = Min(myPosition + theStep, 1.);
170
171   // show progress indicator; note that this call is protected by
172   // the same mutex to avoid concurrency and ensure that this call
173   // to Show() will see the position exactly as it was just set above
174   Show(theScope, Standard_False);
175 }
176
177 #endif // _Message_ProgressIndicator_HeaderFile