1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
/*
* Cppcheck - A tool for static C/C++ code analysis
* Copyright (C) 2007-2016 Cppcheck team.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef THREADEXECUTOR_H
#define THREADEXECUTOR_H
#include <map>
#include <string>
#include <list>
#include "errorlogger.h"
#include "importproject.h"
#if (defined(__GNUC__) || defined(__sun)) && !defined(__MINGW32__)
#define THREADING_MODEL_FORK
#elif defined(_WIN32)
#define THREADING_MODEL_WIN
#include <windows.h>
#endif
class Settings;
/// @addtogroup CLI
/// @{
/**
* This class will take a list of filenames and settings and check then
* all files using threads.
*/
class ThreadExecutor : public ErrorLogger {
public:
ThreadExecutor(const std::map<std::string, std::size_t> &files, Settings &settings, ErrorLogger &_errorLogger);
virtual ~ThreadExecutor();
unsigned int check();
virtual void reportOut(const std::string &outmsg);
virtual void reportErr(const ErrorLogger::ErrorMessage &msg);
virtual void reportInfo(const ErrorLogger::ErrorMessage &msg);
/**
* @brief Add content to a file, to be used in unit testing.
*
* @param path File name (used as a key to link with real file).
* @param content If the file would be a real file, this should be
* the content of the file.
*/
void addFileContent(const std::string &path, const std::string &content);
private:
const std::map<std::string, std::size_t> &_files;
Settings &_settings;
ErrorLogger &_errorLogger;
unsigned int _fileCount;
#if defined(THREADING_MODEL_FORK)
/** @brief Key is file name, and value is the content of the file */
std::map<std::string, std::string> _fileContents;
private:
enum PipeSignal {REPORT_OUT='1',REPORT_ERROR='2', REPORT_INFO='3', CHILD_END='4'};
/**
* Read from the pipe, parse and handle what ever is in there.
*@return -1 in case of error
* 0 if there is nothing in the pipe to be read
* 1 if we did read something
*/
int handleRead(int rpipe, unsigned int &result);
void writeToPipe(PipeSignal type, const std::string &data);
/**
* Write end of status pipe, different for each child.
* Not used in master process.
*/
std::list<std::string> _errorList;
int _wpipe;
/**
* @brief Check load average condition
* @param nchildren - count of currently runned children
* @return true - if new process can be started
*/
bool checkLoadAverage(size_t nchildren);
public:
/**
* @return true if support for threads exist.
*/
static bool isEnabled() {
return true;
}
#elif defined(THREADING_MODEL_WIN)
private:
enum MessageType {REPORT_ERROR, REPORT_INFO};
std::map<std::string, std::string> _fileContents;
std::map<std::string, std::size_t>::const_iterator _itNextFile;
std::list<ImportProject::FileSettings>::const_iterator _itNextFileSettings;
std::size_t _processedFiles;
std::size_t _totalFiles;
std::size_t _processedSize;
std::size_t _totalFileSize;
CRITICAL_SECTION _fileSync;
std::list<std::string> _errorList;
CRITICAL_SECTION _errorSync;
CRITICAL_SECTION _reportSync;
void report(const ErrorLogger::ErrorMessage &msg, MessageType msgType);
static unsigned __stdcall threadProc(void*);
public:
/**
* @return true if support for threads exist.
*/
static bool isEnabled() {
return true;
}
#else
public:
/**
* @return true if support for threads exist.
*/
static bool isEnabled() {
return false;
}
#endif
private:
/** disabled copy constructor */
ThreadExecutor(const ThreadExecutor &);
/** disabled assignment operator */
void operator=(const ThreadExecutor &);
};
/// @}
#endif // THREADEXECUTOR_H
|