Branch data Line data Source code
1 : : // *****************************************************************************
2 : : /*!
3 : : \file src/Base/Progress.hpp
4 : : \copyright 2012-2015 J. Bakosi,
5 : : 2016-2018 Los Alamos National Security, LLC.,
6 : : 2019-2021 Triad National Security, LLC.,
7 : : 2022-2024 J. Bakosi
8 : : All rights reserved. See the LICENSE file for details.
9 : : \brief Simple progress indicator
10 : : \details Simple progress indicator.
11 : : */
12 : : // *****************************************************************************
13 : : #ifndef Progress_h
14 : : #define Progress_h
15 : :
16 : : #include <array>
17 : : #include <functional>
18 : :
19 : : #include "TaggedTuple.hpp"
20 : : #include "Print.hpp"
21 : :
22 : : namespace tk {
23 : :
24 : : //! Simple progress class for outputing progress indicators during a task
25 : : //! \details This is a helper class to abstract away the details of using
26 : : //! Print::progress() used to output progress reports to the screen during
27 : : //! a task consisting of multiple sub-tasks happening at the same time. The
28 : : //! template argument is a compile-time integer which is the number of
29 : : //! independent sub-tasks the progress indicator receives messages for and
30 : : //! counts them independtly toward multiple maxima.
31 : : template< std::size_t N >
32 : 0 : class Progress {
33 : :
34 : : public:
35 : : //! Constructor
36 : : //! \param[in] feedback Whether to send sub-task feedback to host
37 : : //! \param[in] prefix Strings to output prefixing the progress report
38 : : //! \param[in] legend Legend for each prefix to output at start
39 : : //! \param[in] max Array of integers equaling the max number of items to be
40 : : //! expected per sub-task
41 : 506 : explicit Progress( bool feedback,
42 : : const std::array< std::string, N >& prefix,
43 : : const std::array< std::string, N >& legend,
44 : : std::array< int, N >&& max = std::array< int, N >() )
45 : 506 : : m_feedback( feedback ),
46 : 506 : m_prefix( std::move(prefix) ),
47 [ + - ]: 506 : m_legend( std::move(legend) ),
48 : 506 : m_finished( false ),
49 : 506 : m_progress_size( 0 ),
50 : 506 : m_max( std::move(max) )
51 : : {
52 : : m_done.fill( 0 );
53 : 506 : }
54 : :
55 : : //! Start counting sub-tasks outputing an intial task message
56 : : //! \param[in] print Pretty printer object to use for printing progress
57 : : //! \param[in] msg Message to output to screen. This message should be
58 : : //! descriptive of all the sub-tasks we are responsible for. I.e., this
59 : : //! is usually a list of multiple sub-tasks happening at the same time.
60 : : //! Appending to msg we also output the legend of subtasks in parentheses.
61 [ + + ]: 484 : void start( const Print& print, const std::string& msg ) {
62 : : std::string legend;
63 [ + + ]: 484 : if (m_feedback) {
64 [ + - ]: 22 : legend.append( " (" );
65 [ + - ][ + + ]: 110 : for (const auto& l : m_legend) legend.append( l + ", " );
66 : : legend.pop_back();
67 : : legend.pop_back();
68 [ + - ]: 22 : legend.append( ")" );
69 : : }
70 [ + - ]: 484 : legend.append( " ..." );
71 [ + - ][ + - ]: 484 : print.diagstart( msg + legend );
[ - - ]
72 [ + + ]: 484 : m_progress_size = 0;
73 : 484 : }
74 : :
75 : : //! \brief Start counting sub-tasks outputing an intial task message and set
76 : : //! max number of items to be expected per sub-task
77 : : //! \param[in] print Pretty printer object to use for printing progress
78 : : //! \param[in] msg Message to output to screen. This message should be
79 : : //! descriptive of all the sub-tasks we are responsible for. I.e., this
80 : : //! is usually a list of multiple sub-tasks happening at the same time.
81 : : //! \param[in] max Array of integers equaling the max number of items to be
82 : : //! expected per sub-task
83 : : //! \details This function can be used to do the same as start( msg ) and
84 : : //! update/reset the max number of items per sub-task in case they are not
85 : : //! all yet available when the constructor is called.
86 : : void start( const Print& print,
87 : : const std::string& msg,
88 : : std::array< int, N >&& max )
89 : : {
90 : 484 : m_max = std::move(max);
91 [ + - ][ + - ]: 484 : start( print, msg );
92 : 484 : }
93 : :
94 : : //! Receive an update to a sub-task counter and update progress report
95 : : //! \param[in] print Pretty printer object to use for printing progress
96 : : //! \details The template argument indexes the sub-task. A compile-time
97 : : //! assert emits an error in case it is out of bounds.
98 [ + + ]: 272 : template< std::size_t i > void inc( const Print& print ) {
99 : : static_assert( i < N, "Indexing out of bounds" );
100 : 272 : ++m_done[i];
101 [ + + ]: 272 : if (!m_finished) report( print );
102 : 272 : }
103 : :
104 : : //! Finish progress report updating it one last time
105 : : //! \param[in] print Pretty printer object to use for printing progress
106 : : //! \details When this function is called, all sub-tasks are assumed to be
107 : : //! finished, i.e., assumed to have reached their respective maximum
108 : : //! values. Thus we update our 'done' array to be equal to 'max' and output
109 : : //! the progress report one final time before outputing 'done'. When this
110 : : //! function is called it is possible that not all sub-task counters have
111 : : //! reached their maximum, which can happen if the final reduction (if
112 : : //! exists), signaling the absolute end of a task (consisting of multiple
113 : : //! sub-tasks we count counters for), is scheduled before (or is faster)
114 : : //! than as the individual sub-task counting messages arrive. Even if that
115 : : //! is the case, this call "officially" finishes all sub-tasks, and outputs
116 : : //! the progress report using the max values for all sub-tasks to leave a
117 : : //! consistent screen output finishing the task.
118 : 484 : void end( const Print& print ) {
119 : 484 : m_finished = true;
120 : 484 : m_done = m_max;
121 : : report( print );
122 : 484 : print.diagend( "done" );
123 : 484 : }
124 : :
125 : : private:
126 : : bool m_feedback; //!< Whether to send sub-task feedback to host
127 : : const std::array< std::string, N > m_prefix; //!< Sub-task prefixes
128 : : const std::array< std::string, N > m_legend; //!< Sub-task legend
129 : : bool m_finished; //!< Whether task has finished
130 : : std::size_t m_progress_size;//!< Size of previous progress report
131 : : std::array< int, N > m_max; //!< Max number of items per sub-task
132 : : std::array< int, N > m_done;//!< Number of items done per sub-task
133 : :
134 : : //! Output progress report to screen
135 : : //! \param[in] print Pretty printer object to use for printing progress
136 : : //! \details This output contains a status on each of the multiple sub-task
137 : : //! counters as they all work towards their respective maxima.
138 : : //! \see Print::progress()
139 : : void report( const Print& print ) {
140 [ + + ][ + + ]: 735 : if (m_feedback)
[ + + ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
141 : 238 : print.progress< N >( m_prefix, m_done, m_max, m_progress_size );
142 : : }
143 : : };
144 : :
145 : : } // tk::
146 : :
147 : : #endif // Progress_h
|