1919#include " threadexecutor.h"
2020
2121#include " color.h"
22+ #include " config.h"
2223#include " cppcheck.h"
2324#include " cppcheckexecutor.h"
2425#include " errorlogger.h"
@@ -45,97 +46,158 @@ ThreadExecutor::ThreadExecutor(const std::map<std::string, std::size_t> &files,
4546ThreadExecutor::~ThreadExecutor ()
4647{}
4748
48- class ThreadExecutor ::SyncLogForwarder : public ErrorLogger
49+ class Data
4950{
5051public:
51- explicit SyncLogForwarder (ThreadExecutor &threadExecutor)
52- : mThreadExecutor(threadExecutor), mProcessedFiles(0 ), mTotalFiles(0 ), mProcessedSize(0 ) {
53-
54- const std::map<std::string, std::size_t >& files = mThreadExecutor .mFiles ;
55- mItNextFile = files.begin ();
56- mItNextFileSettings = mThreadExecutor .mSettings .project .fileSettings .begin ();
52+ Data (const std::map<std::string, std::size_t > &files, const std::list<ImportProject::FileSettings> &fileSettings)
53+ : mFiles (files), mFileSettings (fileSettings), mProcessedFiles (0 ), mProcessedSize (0 )
54+ {
55+ mItNextFile = mFiles .begin ();
56+ mItNextFileSettings = mFileSettings .begin ();
5757
58- mTotalFiles = files .size () + mThreadExecutor . mSettings . project . fileSettings .size ();
59- mTotalFileSize = std::accumulate (files .cbegin (), files .cend (), std::size_t (0 ), [](std::size_t v, const std::pair<std::string, std::size_t >& p) {
58+ mTotalFiles = mFiles .size () + mFileSettings .size ();
59+ mTotalFileSize = std::accumulate (mFiles .cbegin (), mFiles .cend (), std::size_t (0 ), [](std::size_t v, const std::pair<std::string, std::size_t >& p) {
6060 return v + p.second ;
6161 });
6262 }
6363
64- void reportOut (const std::string &outmsg, Color c) override
65- {
66- std::lock_guard<std::mutex> lg (mReportSync );
67-
68- mThreadExecutor .mErrorLogger .reportOut (outmsg, c);
64+ bool finished () {
65+ std::lock_guard<std::mutex> l (mFileSync );
66+ return mItNextFile == mFiles .cend () && mItNextFileSettings == mFileSettings .cend ();
6967 }
7068
71- void reportErr (const ErrorMessage &msg) override {
72- report (msg, MessageType::REPORT_ERROR);
73- }
69+ bool next (const std::string *&file, const ImportProject::FileSettings *&fs, std::size_t &fileSize) {
70+ std::lock_guard<std::mutex> l (mFileSync );
71+ if (mItNextFile != mFiles .end ()) {
72+ file = &mItNextFile ->first ;
73+ fileSize = mItNextFile ->second ;
74+ ++mItNextFile ;
75+ return true ;
76+ }
77+ if (mItNextFileSettings != mFileSettings .end ()) {
78+ fs = &(*mItNextFileSettings );
79+ fileSize = 0 ;
80+ ++mItNextFileSettings ;
81+ return true ;
82+ }
7483
75- void reportInfo (const ErrorMessage &msg) override {
76- report (msg, MessageType::REPORT_INFO);
84+ return false ;
7785 }
7886
79- ThreadExecutor & mThreadExecutor ;
80-
87+ private:
88+ const std::map<std::string, std:: size_t > & mFiles ;
8189 std::map<std::string, std::size_t >::const_iterator mItNextFile ;
90+ const std::list<ImportProject::FileSettings> &mFileSettings ;
8291 std::list<ImportProject::FileSettings>::const_iterator mItNextFileSettings ;
8392
93+ public:
8494 std::size_t mProcessedFiles ;
8595 std::size_t mTotalFiles ;
8696 std::size_t mProcessedSize ;
8797 std::size_t mTotalFileSize ;
8898
8999 std::mutex mFileSync ;
90- std::mutex mErrorSync ;
100+ };
101+
102+ class SyncLogForwarder : public ErrorLogger
103+ {
104+ public:
105+ explicit SyncLogForwarder (ThreadExecutor &threadExecutor, ErrorLogger &errorLogger)
106+ : mThreadExecutor(threadExecutor), mErrorLogger(errorLogger) {}
107+
108+ void reportOut (const std::string &outmsg, Color c) override
109+ {
110+ std::lock_guard<std::mutex> lg (mReportSync );
111+
112+ mErrorLogger .reportOut (outmsg, c);
113+ }
114+
115+ void reportErr (const ErrorMessage &msg) override {
116+ report (msg, MessageType::REPORT_ERROR);
117+ }
118+
119+ void reportInfo (const ErrorMessage &msg) override {
120+ report (msg, MessageType::REPORT_INFO);
121+ }
122+
91123 std::mutex mReportSync ;
92124
93125private:
94126 enum class MessageType {REPORT_ERROR, REPORT_INFO};
95127
96128 void report (const ErrorMessage &msg, MessageType msgType)
97129 {
98- if (mThreadExecutor .mSettings . nomsg . isSuppressed (msg))
130+ if (! mThreadExecutor .hasToLog (msg))
99131 return ;
100132
101- // Alert only about unique errors
102- bool reportError = false ;
133+ std::lock_guard<std::mutex> lg (mReportSync );
103134
104- {
105- std::string errmsg = msg.toString (mThreadExecutor .mSettings .verbose );
135+ switch (msgType) {
136+ case MessageType::REPORT_ERROR:
137+ mErrorLogger .reportErr (msg);
138+ break ;
139+ case MessageType::REPORT_INFO:
140+ mErrorLogger .reportInfo (msg);
141+ break ;
142+ }
143+ }
106144
107- std::lock_guard<std::mutex> lg (mErrorSync );
108- if (std::find (mThreadExecutor .mErrorList .cbegin (), mThreadExecutor .mErrorList .cend (), errmsg) == mThreadExecutor .mErrorList .cend ()) {
109- mThreadExecutor .mErrorList .emplace_back (std::move (errmsg));
110- reportError = true ;
111- }
145+ ThreadExecutor &mThreadExecutor ;
146+ ErrorLogger &mErrorLogger ;
147+ };
148+
149+ static unsigned int STDCALL threadProc (Data *data, SyncLogForwarder* logForwarder, const Settings &settings)
150+ {
151+ unsigned int result = 0 ;
152+
153+ for (;;) {
154+ if (data->finished ()) {
155+ break ;
112156 }
113157
114- if (reportError) {
115- std::lock_guard<std::mutex> lg (mReportSync );
158+ const std::string *file = nullptr ;
159+ const ImportProject::FileSettings *fs = nullptr ;
160+ std::size_t fileSize;
161+ if (!data->next (file, fs, fileSize))
162+ break ;
116163
117- switch (msgType) {
118- case MessageType::REPORT_ERROR:
119- mThreadExecutor .mErrorLogger .reportErr (msg);
120- break ;
121- case MessageType::REPORT_INFO:
122- mThreadExecutor .mErrorLogger .reportInfo (msg);
123- break ;
164+ CppCheck fileChecker (*logForwarder, false , CppCheckExecutor::executeCommand);
165+ fileChecker.settings () = settings;
166+
167+ if (fs) {
168+ // file settings..
169+ result += fileChecker.check (*fs);
170+ if (settings.clangTidy )
171+ fileChecker.analyseClangTidy (*fs);
172+ } else {
173+ // Read file from a file
174+ result += fileChecker.check (*file);
175+ }
176+
177+ {
178+ std::lock_guard<std::mutex> l (data->mFileSync );
179+ data->mProcessedSize += fileSize;
180+ data->mProcessedFiles ++;
181+ if (!settings.quiet ) {
182+ std::lock_guard<std::mutex> lg (logForwarder->mReportSync );
183+ CppCheckExecutor::reportStatus (data->mProcessedFiles , data->mTotalFiles , data->mProcessedSize , data->mTotalFileSize );
124184 }
125185 }
126186 }
127- };
187+ return result;
188+ }
128189
129190unsigned int ThreadExecutor::check ()
130191{
131192 std::vector<std::future<unsigned int >> threadFutures;
132193 threadFutures.reserve (mSettings .jobs );
133194
134- SyncLogForwarder logforwarder (*this );
195+ Data data (mFiles , mSettings .project .fileSettings );
196+ SyncLogForwarder logforwarder (*this , mErrorLogger );
135197
136198 for (unsigned int i = 0 ; i < mSettings .jobs ; ++i) {
137199 try {
138- threadFutures.emplace_back (std::async (std::launch::async, threadProc, &logforwarder));
200+ threadFutures.emplace_back (std::async (std::launch::async, & threadProc, &data, & logforwarder, mSettings ));
139201 }
140202 catch (const std::system_error &e) {
141203 std::cerr << " #### ThreadExecutor::check exception :" << e.what () << std::endl;
@@ -147,53 +209,3 @@ unsigned int ThreadExecutor::check()
147209 return v + f.get ();
148210 });
149211}
150-
151- unsigned int STDCALL ThreadExecutor::threadProc (SyncLogForwarder* logForwarder)
152- {
153- unsigned int result = 0 ;
154-
155- std::map<std::string, std::size_t >::const_iterator &itFile = logForwarder->mItNextFile ;
156- std::list<ImportProject::FileSettings>::const_iterator &itFileSettings = logForwarder->mItNextFileSettings ;
157-
158- // guard static members of CppCheck against concurrent access
159- logForwarder->mFileSync .lock ();
160-
161- for (;;) {
162- if (itFile == logForwarder->mThreadExecutor .mFiles .cend () && itFileSettings == logForwarder->mThreadExecutor .mSettings .project .fileSettings .cend ()) {
163- logForwarder->mFileSync .unlock ();
164- break ;
165- }
166-
167- CppCheck fileChecker (*logForwarder, false , CppCheckExecutor::executeCommand);
168- fileChecker.settings () = logForwarder->mThreadExecutor .mSettings ;
169-
170- std::size_t fileSize = 0 ;
171- if (itFile != logForwarder->mThreadExecutor .mFiles .end ()) {
172- const std::string &file = itFile->first ;
173- fileSize = itFile->second ;
174- ++itFile;
175-
176- logForwarder->mFileSync .unlock ();
177-
178- // Read file from a file
179- result += fileChecker.check (file);
180- } else { // file settings..
181- const ImportProject::FileSettings &fs = *itFileSettings;
182- ++itFileSettings;
183- logForwarder->mFileSync .unlock ();
184- result += fileChecker.check (fs);
185- if (logForwarder->mThreadExecutor .mSettings .clangTidy )
186- fileChecker.analyseClangTidy (fs);
187- }
188-
189- logForwarder->mFileSync .lock ();
190-
191- logForwarder->mProcessedSize += fileSize;
192- logForwarder->mProcessedFiles ++;
193- if (!logForwarder->mThreadExecutor .mSettings .quiet ) {
194- std::lock_guard<std::mutex> lg (logForwarder->mReportSync );
195- CppCheckExecutor::reportStatus (logForwarder->mProcessedFiles , logForwarder->mTotalFiles , logForwarder->mProcessedSize , logForwarder->mTotalFileSize );
196- }
197- }
198- return result;
199- }
0 commit comments