Fix ticket #113 (Add support for multi core CPUs and -w parameter to specifify amount of worker threads)
This commit is contained in:
parent
439b8c4051
commit
61587c42ae
|
@ -105,11 +105,12 @@ man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/
|
||||||
<arg choice="opt"><option>--all</option></arg>
|
<arg choice="opt"><option>--all</option></arg>
|
||||||
<arg choice="opt"><option>--force</option></arg>
|
<arg choice="opt"><option>--force</option></arg>
|
||||||
<arg choice="opt"><option>--help</option></arg>
|
<arg choice="opt"><option>--help</option></arg>
|
||||||
<arg choice="opt"><option>-Idir</option></arg>
|
<arg choice="opt"><option>-I[dir]</option></arg>
|
||||||
<arg choice="opt"><option>--quiet</option></arg>
|
<arg choice="opt"><option>--quiet</option></arg>
|
||||||
<arg choice="opt"><option>--style</option></arg>
|
<arg choice="opt"><option>--style</option></arg>
|
||||||
<arg choice="opt"><option>--unused-functions</option></arg>
|
<arg choice="opt"><option>--unused-functions</option></arg>
|
||||||
<arg choice="opt"><option>--verbose</option></arg>
|
<arg choice="opt"><option>--verbose</option></arg>
|
||||||
|
<arg choice="opt"><option>-w[workers]</option></arg>
|
||||||
<arg choice="opt"><option>--xml</option></arg>
|
<arg choice="opt"><option>--xml</option></arg>
|
||||||
<arg choice="opt"><option>file or path</option></arg>
|
<arg choice="opt"><option>file or path</option></arg>
|
||||||
<arg choice="plain"><option>...</option></arg>
|
<arg choice="plain"><option>...</option></arg>
|
||||||
|
@ -153,7 +154,7 @@ default.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>-I <dir></option></term>
|
<term><option>-I [dir]</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>Give include path. Give several -I parameters to give several paths. First given path is checked first. If paths are relative to source
|
<para>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.</para>
|
files, this is not needed.</para>
|
||||||
|
@ -186,6 +187,12 @@ files, this is not needed.</para>
|
||||||
<para>More detailed error reports</para>
|
<para>More detailed error reports</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-w [workers]</option></term>
|
||||||
|
<listitem>
|
||||||
|
<para>Start [workers] threads to do the checking work.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--xml</option></term>
|
<term><option>--xml</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
|
|
@ -146,6 +146,39 @@ std::string CppCheck::parseFromArgs(int argc, const char* const argv[])
|
||||||
_includePaths.push_back(path);
|
_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)
|
else if (strncmp(argv[i], "-", 1) == 0 || strncmp(argv[i], "--", 2) == 0)
|
||||||
{
|
{
|
||||||
return "cppcheck: error: unrecognized command line option \"" + std::string(argv[i]) + "\"\n";
|
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"
|
" -f, --force Force checking on files that have \"too many\"\n"
|
||||||
" configurations\n"
|
" configurations\n"
|
||||||
" -h, --help Print this help\n"
|
" -h, --help Print this help\n"
|
||||||
" -I <dir> 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"
|
" several paths. First given path is checked first. If\n"
|
||||||
" paths are relative to source files, this is not needed\n"
|
" paths are relative to source files, this is not needed\n"
|
||||||
" -q, --quiet Only print error messages\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"
|
" --unused-functions Check if there are unused functions\n"
|
||||||
" --vcl Suppress messages about memory leaks when using VCL classes\n"
|
" --vcl Suppress messages about memory leaks when using VCL classes\n"
|
||||||
" -v, --verbose More detailed error reports\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"
|
" --xml Write results in xml to error stream.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Example usage:\n"
|
"Example usage:\n"
|
||||||
|
|
|
@ -47,11 +47,15 @@ unsigned int CppCheckExecutor::check(int argc, const char* const argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int returnValue = 0;
|
unsigned int returnValue = 0;
|
||||||
if (1)
|
if (_settings._workers == 1)
|
||||||
{
|
{
|
||||||
// Single process
|
// Single process
|
||||||
returnValue = cppCheck.check();
|
returnValue = cppCheck.check();
|
||||||
}
|
}
|
||||||
|
else if (!ThreadExecutor::isEnabled())
|
||||||
|
{
|
||||||
|
std::cout << "No thread support yet implemented for this platform." << std::endl;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Multiple processes
|
// Multiple processes
|
||||||
|
|
|
@ -31,6 +31,7 @@ Settings::Settings()
|
||||||
_unusedFunctions = false;
|
_unusedFunctions = false;
|
||||||
_security = false;
|
_security = false;
|
||||||
_vcl = false;
|
_vcl = false;
|
||||||
|
_workers = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Settings::~Settings()
|
Settings::~Settings()
|
||||||
|
|
|
@ -51,6 +51,10 @@ public:
|
||||||
|
|
||||||
/** Disable warnings for VCL classes */
|
/** Disable warnings for VCL classes */
|
||||||
bool _vcl;
|
bool _vcl;
|
||||||
|
|
||||||
|
/** How many processes/threads should do checking at the same
|
||||||
|
time. Default is 1. */
|
||||||
|
unsigned int _workers;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SETTINGS_H
|
#endif // SETTINGS_H
|
||||||
|
|
|
@ -19,18 +19,12 @@
|
||||||
|
|
||||||
#include "threadexecutor.h"
|
#include "threadexecutor.h"
|
||||||
#include "cppcheck.h"
|
#include "cppcheck.h"
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
/**
|
|
||||||
This implementation is currently for Linux only and disabled with #if 0 until
|
|
||||||
proper way is invented.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#if defined(__GNUC__) && !defined(__MINGW32__)
|
||||||
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
ThreadExecutor::ThreadExecutor(const std::vector<std::string> &filenames, const Settings &settings, ErrorLogger &errorLogger)
|
ThreadExecutor::ThreadExecutor(const std::vector<std::string> &filenames, const Settings &settings, ErrorLogger &errorLogger)
|
||||||
: _filenames(filenames), _settings(settings), _errorLogger(errorLogger), _fileCount(0)
|
: _filenames(filenames), _settings(settings), _errorLogger(errorLogger), _fileCount(0)
|
||||||
|
@ -43,6 +37,12 @@ ThreadExecutor::~ThreadExecutor()
|
||||||
//dtor
|
//dtor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
////// This code is for __GNUC__ only /////////////////////////////////////////
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && !defined(__MINGW32__)
|
||||||
|
|
||||||
bool ThreadExecutor::handleRead(unsigned int &result)
|
bool ThreadExecutor::handleRead(unsigned int &result)
|
||||||
{
|
{
|
||||||
char type = 0;
|
char type = 0;
|
||||||
|
@ -53,7 +53,7 @@ bool ThreadExecutor::handleRead(unsigned int &result)
|
||||||
|
|
||||||
if (type != '1' && type != '2' && type != '3')
|
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);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ unsigned int ThreadExecutor::check()
|
||||||
for (unsigned int i = 0; i < _filenames.size(); i++)
|
for (unsigned int i = 0; i < _filenames.size(); i++)
|
||||||
{
|
{
|
||||||
// Keep only wanted amount of child processes running at a time.
|
// Keep only wanted amount of child processes running at a time.
|
||||||
if (childCount >= 2)
|
if (childCount >= _settings._workers)
|
||||||
{
|
{
|
||||||
while (handleRead(result))
|
while (handleRead(result))
|
||||||
{
|
{
|
||||||
|
@ -187,5 +187,22 @@ void ThreadExecutor::reportStatus(unsigned int /*index*/, unsigned int /*max*/)
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#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
|
#endif
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
*/
|
*/
|
||||||
class ThreadExecutor : public ErrorLogger
|
class ThreadExecutor : public ErrorLogger
|
||||||
{
|
{
|
||||||
#if 0
|
|
||||||
public:
|
public:
|
||||||
ThreadExecutor(const std::vector<std::string> &filenames, const Settings &settings, ErrorLogger &_errorLogger);
|
ThreadExecutor(const std::vector<std::string> &filenames, const Settings &settings, ErrorLogger &_errorLogger);
|
||||||
virtual ~ThreadExecutor();
|
virtual ~ThreadExecutor();
|
||||||
|
@ -39,28 +38,37 @@ public:
|
||||||
virtual void reportOut(const std::string &outmsg);
|
virtual void reportOut(const std::string &outmsg);
|
||||||
virtual void reportErr(const ErrorLogger::ErrorMessage &msg);
|
virtual void reportErr(const ErrorLogger::ErrorMessage &msg);
|
||||||
virtual void reportStatus(unsigned int index, unsigned int max);
|
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<std::string> &_filenames;
|
const std::vector<std::string> &_filenames;
|
||||||
const Settings &_settings;
|
const Settings &_settings;
|
||||||
ErrorLogger &_errorLogger;
|
ErrorLogger &_errorLogger;
|
||||||
int _pipe[2];
|
|
||||||
unsigned int _fileCount;
|
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
|
#else
|
||||||
public:
|
public:
|
||||||
ThreadExecutor(const std::vector<std::string> &filenames, const Settings &settings, ErrorLogger &_errorLogger) {};
|
/**
|
||||||
virtual ~ThreadExecutor() {};
|
* @return true if support for threads exist.
|
||||||
unsigned int check()
|
*/
|
||||||
|
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
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // THREADEXECUTOR_H
|
#endif // THREADEXECUTOR_H
|
||||||
|
|
|
@ -181,7 +181,7 @@ int main()
|
||||||
fout << " std::string toXML() const;\n";
|
fout << " std::string toXML() const;\n";
|
||||||
fout << " std::string toText() const;\n";
|
fout << " std::string toText() const;\n";
|
||||||
fout << " std::string serialize() 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 << " private:\n";
|
||||||
fout << " std::list<FileLocation> _callStack;\n";
|
fout << " std::list<FileLocation> _callStack;\n";
|
||||||
fout << " std::string _severity;\n";
|
fout << " std::string _severity;\n";
|
||||||
|
|
Loading…
Reference in New Issue