From 61587c42aee920532954c66e39be317bd4947827 Mon Sep 17 00:00:00 2001 From: Reijo Tomperi Date: Fri, 20 Feb 2009 19:40:42 +0000 Subject: [PATCH] Fix ticket #113 (Add support for multi core CPUs and -w parameter to specifify amount of worker threads) --- man/cppcheck.1.xml | 11 +++++++++-- src/cppcheck.cpp | 36 +++++++++++++++++++++++++++++++++++- src/cppcheckexecutor.cpp | 6 +++++- src/settings.cpp | 1 + src/settings.h | 4 ++++ src/threadexecutor.cpp | 39 ++++++++++++++++++++++++++++----------- src/threadexecutor.h | 34 +++++++++++++++++++++------------- tools/errmsg.cpp | 2 +- 8 files changed, 104 insertions(+), 29 deletions(-) diff --git a/man/cppcheck.1.xml b/man/cppcheck.1.xml index 7302b06ee..0aee5a760 100644 --- a/man/cppcheck.1.xml +++ b/man/cppcheck.1.xml @@ -105,11 +105,12 @@ man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/ - + + @@ -153,7 +154,7 @@ default. - + Give include path. Give several -I parameters to give several paths. First given path is checked first. If paths are relative to source files, this is not needed. @@ -186,6 +187,12 @@ files, this is not needed. More detailed error reports + + + + Start [workers] threads to do the checking work. + + diff --git a/src/cppcheck.cpp b/src/cppcheck.cpp index 4acddb0e0..e2d4ed68b 100644 --- a/src/cppcheck.cpp +++ b/src/cppcheck.cpp @@ -146,6 +146,39 @@ std::string CppCheck::parseFromArgs(int argc, const char* const argv[]) _includePaths.push_back(path); } +// Include paths + else if (strcmp(argv[i], "-w") == 0 || + strncmp(argv[i], "-w", 2) == 0) + { + std::string numberString; + + // "-w 3" + if (strcmp(argv[i], "-w") == 0) + { + ++i; + if (i >= argc) + return "cppcheck: argument to '-w' is missing\n"; + + numberString = argv[i]; + } + + // "-w3" + else if (strncmp(argv[i], "-w", 2) == 0) + { + numberString = argv[i]; + numberString = numberString.substr(2); + } + + std::istringstream iss(numberString); + if (!(iss >> _settings._workers)) + return "cppcheck: argument to '-w' is not a number\n"; + + if (_settings._workers > 1000) + { + return "cppcheck: argument for '-w' is allowed to be 1000 at max\n"; + } + } + else if (strncmp(argv[i], "-", 1) == 0 || strncmp(argv[i], "--", 2) == 0) { return "cppcheck: error: unrecognized command line option \"" + std::string(argv[i]) + "\"\n"; @@ -184,7 +217,7 @@ std::string CppCheck::parseFromArgs(int argc, const char* const argv[]) " -f, --force Force checking on files that have \"too many\"\n" " configurations\n" " -h, --help Print this help\n" - " -I Give include path. Give several -I parameters to give\n" + " -I [dir] Give include path. Give several -I parameters to give\n" " several paths. First given path is checked first. If\n" " paths are relative to source files, this is not needed\n" " -q, --quiet Only print error messages\n" @@ -192,6 +225,7 @@ std::string CppCheck::parseFromArgs(int argc, const char* const argv[]) " --unused-functions Check if there are unused functions\n" " --vcl Suppress messages about memory leaks when using VCL classes\n" " -v, --verbose More detailed error reports\n" + " -w [workers] Start [workers] threads to do the checking work.\n" " --xml Write results in xml to error stream.\n" "\n" "Example usage:\n" diff --git a/src/cppcheckexecutor.cpp b/src/cppcheckexecutor.cpp index 4cdd2e1b7..aae21865d 100644 --- a/src/cppcheckexecutor.cpp +++ b/src/cppcheckexecutor.cpp @@ -47,11 +47,15 @@ unsigned int CppCheckExecutor::check(int argc, const char* const argv[]) } unsigned int returnValue = 0; - if (1) + if (_settings._workers == 1) { // Single process returnValue = cppCheck.check(); } + else if (!ThreadExecutor::isEnabled()) + { + std::cout << "No thread support yet implemented for this platform." << std::endl; + } else { // Multiple processes diff --git a/src/settings.cpp b/src/settings.cpp index dc6282af4..77830c56b 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -31,6 +31,7 @@ Settings::Settings() _unusedFunctions = false; _security = false; _vcl = false; + _workers = 1; } Settings::~Settings() diff --git a/src/settings.h b/src/settings.h index b73d5cfa6..6d88054b2 100644 --- a/src/settings.h +++ b/src/settings.h @@ -51,6 +51,10 @@ public: /** Disable warnings for VCL classes */ bool _vcl; + + /** How many processes/threads should do checking at the same + time. Default is 1. */ + unsigned int _workers; }; #endif // SETTINGS_H diff --git a/src/threadexecutor.cpp b/src/threadexecutor.cpp index a87c44418..efcd2b5b6 100644 --- a/src/threadexecutor.cpp +++ b/src/threadexecutor.cpp @@ -19,18 +19,12 @@ #include "threadexecutor.h" #include "cppcheck.h" - -#if 0 - -/** -This implementation is currently for Linux only and disabled with #if 0 until -proper way is invented. - */ - -#include #include +#if defined(__GNUC__) && !defined(__MINGW32__) +#include #include #include +#endif ThreadExecutor::ThreadExecutor(const std::vector &filenames, const Settings &settings, ErrorLogger &errorLogger) : _filenames(filenames), _settings(settings), _errorLogger(errorLogger), _fileCount(0) @@ -43,6 +37,12 @@ ThreadExecutor::~ThreadExecutor() //dtor } +/////////////////////////////////////////////////////////////////////////////// +////// This code is for __GNUC__ only ///////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +#if defined(__GNUC__) && !defined(__MINGW32__) + bool ThreadExecutor::handleRead(unsigned int &result) { char type = 0; @@ -53,7 +53,7 @@ bool ThreadExecutor::handleRead(unsigned int &result) if (type != '1' && type != '2' && type != '3') { - std::cerr << "#### ThreadExecutor::handleRead error, type was:" << type << std::endl; + std::cerr << "#### You found a bug from cppcheck.\nThreadExecutor::handleRead error, type was:" << type << std::endl; exit(0); } @@ -112,7 +112,7 @@ unsigned int ThreadExecutor::check() for (unsigned int i = 0; i < _filenames.size(); i++) { // Keep only wanted amount of child processes running at a time. - if (childCount >= 2) + if (childCount >= _settings._workers) { while (handleRead(result)) { @@ -187,5 +187,22 @@ void ThreadExecutor::reportStatus(unsigned int /*index*/, unsigned int /*max*/) } #else +unsigned int ThreadExecutor::check() +{ + return 0; +} +void ThreadExecutor::reportOut(const std::string &/*outmsg*/) +{ + +} +void ThreadExecutor::reportErr(const ErrorLogger::ErrorMessage &/*msg*/) +{ + +} + +void ThreadExecutor::reportStatus(unsigned int /*index*/, unsigned int /*max*/) +{ + +} #endif diff --git a/src/threadexecutor.h b/src/threadexecutor.h index b4f28cc0c..53f79d04d 100644 --- a/src/threadexecutor.h +++ b/src/threadexecutor.h @@ -31,7 +31,6 @@ */ class ThreadExecutor : public ErrorLogger { -#if 0 public: ThreadExecutor(const std::vector &filenames, const Settings &settings, ErrorLogger &_errorLogger); virtual ~ThreadExecutor(); @@ -39,28 +38,37 @@ public: virtual void reportOut(const std::string &outmsg); virtual void reportErr(const ErrorLogger::ErrorMessage &msg); virtual void reportStatus(unsigned int index, unsigned int max); -protected: -private: - bool handleRead(unsigned int &result); - void writeToPipe(char type, const std::string &data); +private: const std::vector &_filenames; const Settings &_settings; ErrorLogger &_errorLogger; - int _pipe[2]; unsigned int _fileCount; + +#if defined(__GNUC__) && !defined(__MINGW32__) +private: + bool handleRead(unsigned int &result); + void writeToPipe(char type, const std::string &data); + int _pipe[2]; +public: + /** + * @return true if support for threads exist. + */ + static bool isEnabled() + { + return true; + } #else public: - ThreadExecutor(const std::vector &filenames, const Settings &settings, ErrorLogger &_errorLogger) {}; - virtual ~ThreadExecutor() {}; - unsigned int check() + /** + * @return true if support for threads exist. + */ + static bool isEnabled() { - return 0; + return false; } - virtual void reportOut(const std::string &outmsg) {} - virtual void reportErr(const ErrorLogger::ErrorMessage &msg) {} - virtual void reportStatus(unsigned int index, unsigned int max) {} #endif + }; #endif // THREADEXECUTOR_H diff --git a/tools/errmsg.cpp b/tools/errmsg.cpp index 0cde3e108..a9a59e6ea 100644 --- a/tools/errmsg.cpp +++ b/tools/errmsg.cpp @@ -181,7 +181,7 @@ int main() fout << " std::string toXML() const;\n"; fout << " std::string toText() const;\n"; fout << " std::string serialize() const;\n"; - fout << " bool deserialize( const std::string &data );\n"; + fout << " bool deserialize(const std::string &data);\n"; fout << " private:\n"; fout << " std::list _callStack;\n"; fout << " std::string _severity;\n";