GCC Code Coverage Report


Directory: ./
File: src/PMultiThreadProgress.cpp
Date: 2025-05-16 18:34:22
Exec Total Coverage
Lines: 92 116 79.3%
Branches: 36 75 48.0%

Line Branch Exec Source
1 /***************************************
2 Auteur : Pierre Aubert
3 Mail : pierre.aubert@lapp.in2p3.fr
4 Licence : CeCILL-C
5 ****************************************/
6
7 #include <sys/ioctl.h>
8 #include <sstream>
9 #include <iostream>
10
11 #include "PMultiThreadProgress.h"
12
13 ///Print the parallel progression of the computing
14 /** @param progress : PMultiThreadProgress which print all progress bars
15 * @param refreshSecond : number of second between two refresh of the progress bars
16 */
17 3 void phoenix_print_parallel_progress(PMultiThreadProgress & progress, int refreshSecond){
18
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 3 times.
9 while(!progress.isFinished()){ //While computation is ongoing
19 6 progress.print();
20
1/1
✓ Branch 2 taken 6 times.
6 std::this_thread::sleep_for(std::chrono::seconds(refreshSecond)); //We check status of computation each second
21 }
22 3 progress.printSummary();
23 3 std::cout << "PMultiThreadProgress : Done" << std::endl;
24 3 }
25
26 ///Default constructor of PMultiThreadProgress
27 /** @param nbExpectedProgressBar : number of expected progress bars
28 */
29 4 PMultiThreadProgress::PMultiThreadProgress(size_t nbExpectedProgressBar){
30
1/1
✓ Branch 1 taken 4 times.
4 initialisationPMultiThreadProgress(nbExpectedProgressBar);
31 4 }
32
33 ///Copy constructor of PMultiThreadProgress
34 /** @param other : class to copy
35 */
36 1 PMultiThreadProgress::PMultiThreadProgress(const PMultiThreadProgress & other){
37
1/1
✓ Branch 1 taken 1 times.
1 copyPMultiThreadProgress(other);
38 1 }
39
40 ///Destructor of PMultiThreadProgress
41 10 PMultiThreadProgress::~PMultiThreadProgress(){
42
43 }
44
45 ///Definition of equal operator of PMultiThreadProgress
46 /** @param other : class to copy
47 * @return copied class
48 */
49 1 PMultiThreadProgress & PMultiThreadProgress::operator = (const PMultiThreadProgress & other){
50 1 copyPMultiThreadProgress(other);
51 1 return *this;
52 }
53
54 ///Set the number of expected progress bars in the PMultiThreadProgress
55 /** @param nbExpectedProgressBar : number of expected progress bars
56 */
57 2 void PMultiThreadProgress::setNbExpectedProgressBar(size_t nbExpectedProgressBar){
58 2 p_nbExpectedProgressBar = nbExpectedProgressBar;
59 2 }
60
61 ///Add a progress line
62 /** @param name : name of the progress line
63 * @param progressMax : maximum of progression bar
64 * @return index of the created progress line
65 */
66 6 size_t PMultiThreadProgress::addProgressBar(const PString & name, int progressMax){
67
1/1
✓ Branch 1 taken 6 times.
6 std::lock_guard<std::mutex> guard(p_currentMutex);
68 6 size_t index = p_vecProgressElement.size();
69
1/1
✓ Branch 1 taken 6 times.
6 ProgressElement el;
70 6 el.progress = 0;
71 6 el.prevProgress = -1;
72 6 el.progressMax = progressMax;
73
1/1
✓ Branch 1 taken 6 times.
6 el.name = name;
74 6 el.isEndError = false;
75
1/1
✓ Branch 1 taken 6 times.
6 p_vecProgressElement.push_back(el);
76 6 return index;
77 6 }
78
79 ///Increment the progress of the progress bar at index
80 /** @param index : index of the progress bar to be incremented
81 */
82 23 void PMultiThreadProgress::incrementProgress(size_t index){
83 23 p_vecProgressElement[index].progress++;
84 23 }
85
86 ///Mark the progress bar at index finished with an error
87 /** @param index : index of the progress bar to be modified
88 */
89 void PMultiThreadProgress::setError(size_t index){
90 p_vecProgressElement[index].isEndError = true;
91 }
92
93 ///Say if the PMultiThreadProgress is finished
94 /** @return true if the PMultiThreadProgress is finished, false otherwise
95 */
96 9 bool PMultiThreadProgress::isFinished() const{
97
4/4
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 3 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 3 times.
9 return p_alreadyPrintedLine == p_vecProgressElement.size() && p_vecProgressElement.size() >= p_nbExpectedProgressBar;
98 }
99
100 ///Print the multithread progress bar
101 6 void PMultiThreadProgress::print(){
102
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
6 if(!isModified()){return;} //No need to print
103 3 size_t nbColTerminal = getNbColTerminal();
104 //Clear all the progress bars on screen
105 3 eraseProgressBar(nbColTerminal);
106 //Check if we can print first finshed lines definitely
107 3 printAllFinshedProgressBar();
108 //Update the rest of the progress bars to print
109 3 printProgressBar(nbColTerminal);
110 //We save the previous number of progress bars, in case we print some and add other later
111 3 p_previousNbProgressBar = p_vecProgressElement.size();
112 }
113
114 ///Print a summary of all the progress bars
115 3 void PMultiThreadProgress::printSummary() const{
116 3 size_t nbFail(0lu);
117
2/2
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 3 times.
9 for(VecProgressElement::const_iterator it(p_vecProgressElement.begin()); it != p_vecProgressElement.end(); ++it){
118 6 nbFail += it->isEndError;
119 }
120 3 size_t nbSuccess(p_vecProgressElement.size() - nbFail);
121 3 std::cout << "PMultiThreadProgress : " << p_vecProgressElement.size() << " computations, " << nbSuccess << " success, " << nbFail << " fail" << std::endl;
122 3 }
123
124 ///Copy function of PMultiThreadProgress
125 /** @param other : class to copy
126 */
127 2 void PMultiThreadProgress::copyPMultiThreadProgress(const PMultiThreadProgress & other){
128 2 p_vecProgressElement = other.p_vecProgressElement;
129 2 p_alreadyPrintedLine = other.p_alreadyPrintedLine;
130 2 p_nbExpectedProgressBar = other.p_nbExpectedProgressBar;
131 2 }
132
133 ///Initialisation function of the class PMultiThreadProgress
134 /** @param nbExpectedProgressBar : number of expected progress bars
135 */
136 4 void PMultiThreadProgress::initialisationPMultiThreadProgress(size_t nbExpectedProgressBar){
137 4 p_alreadyPrintedLine = 0lu;
138 4 p_previousNbProgressBar = 0lu;
139 4 p_nbExpectedProgressBar = nbExpectedProgressBar;
140 4 p_vecProgressElement.reserve(nbExpectedProgressBar);
141 4 }
142
143 ///Check if the PMultiThreadProgress has been modified
144 /** @return true if the PMultiThreadProgress has been modified, false otherwise
145 */
146 6 bool PMultiThreadProgress::isModified(){
147
1/1
✓ Branch 1 taken 6 times.
6 std::lock_guard<std::mutex> guard(p_currentMutex);
148 6 bool isModif(false);
149 6 size_t i(p_alreadyPrintedLine);
150
6/6
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 6 times.
9 while(!isModif && i < p_vecProgressElement.size()){
151 3 ProgressElement & el = p_vecProgressElement[i];
152
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3 isModif = el.progress != el.prevProgress || el.isEndError;
153 3 ++i;
154 }
155 6 return isModif;
156 6 }
157
158 ///Erase all progress bars
159 /** @param nbColTerminal : number of columns in the current terminal
160 */
161 3 void PMultiThreadProgress::eraseProgressBar(size_t nbColTerminal){
162
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if(p_previousNbProgressBar == 0lu){return;}
163 //Advances method but can't write anyting
164 std::cerr << "\33[2K\r"; //Remove a line where the cursor is
165 for(size_t i(p_alreadyPrintedLine + 1u); i < p_previousNbProgressBar; ++i){
166 std::cerr << "\033[A"; //Go to one line up
167 std::cerr << "\33[2K\r"; //Remove a line where the cursor is
168 }
169 }
170
171 ///Print all progress bars
172 /** @param nbColTerminal : number of columns in the current terminal
173 */
174 3 void PMultiThreadProgress::printProgressBar(size_t nbColTerminal){
175
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 for(size_t i(p_alreadyPrintedLine); i < p_vecProgressElement.size(); ++i){
176 ProgressElement & el = p_vecProgressElement[i];
177 std::cerr << el.name << " : ";
178 if(el.progress >= el.progressMax || el.isEndError){ //This is a finished progress bar but not finaly drawed
179 if(el.isEndError){
180 std::cerr << "\033[31mError\033[0m";
181 for(size_t j(el.name.size() + 8lu); j < nbColTerminal; ++j){
182 std::cerr << " ";
183 }
184 }else{
185 std::cerr << "\033[32mDone\033[0m";
186 for(size_t j(el.name.size() + 7lu); j < nbColTerminal; ++j){
187 std::cerr << " ";
188 }
189 }
190 }else{
191 int avencement = (100*el.progress)/el.progressMax;
192 std::stringstream strAvencement;
193 strAvencement << avencement;
194 std::cerr << avencement << "%";
195 for(size_t j(el.name.size() + 4lu + strAvencement.str().size()); j < nbColTerminal; ++j){
196 std::cerr << " ";
197 }
198 el.prevProgress = el.progress; //Update previous progress
199 }
200 }
201 3 }
202
203 ///Print all finished progress bars
204 3 void PMultiThreadProgress::printAllFinshedProgressBar(){
205
1/1
✓ Branch 1 taken 3 times.
3 std::lock_guard<std::mutex> guard(p_currentMutex);
206 3 size_t i(p_alreadyPrintedLine);
207
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 3 times.
9 while(i < p_vecProgressElement.size()){
208 6 ProgressElement & el = p_vecProgressElement[i];
209
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
6 if(el.progress >= el.progressMax || el.isEndError){ //This is a finished progress bar
210
2/2
✓ Branch 1 taken 6 times.
✓ Branch 4 taken 6 times.
6 std::cout << el.name << " : ";
211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if(el.isEndError){
212 std::cout << "\033[31mError\033[0m" << std::endl;
213 }else{
214
2/2
✓ Branch 1 taken 6 times.
✓ Branch 4 taken 6 times.
6 std::cout << "\033[32mDone\033[0m" << std::endl;
215 }
216 6 ++p_alreadyPrintedLine;
217 }else{
218 break;
219 }
220 6 ++i;
221 }
222 3 }
223
224 ///Get the number of columns in the current terminal
225 /** @return number of columns in the current terminal
226 */
227 3 size_t PMultiThreadProgress::getNbColTerminal() const{
228 struct winsize w;
229 3 ioctl(0, TIOCGWINSZ, &w);
230 3 return w.ws_col;
231 }
232
233
234