From: Maksym Mamontov <madf@madf.info> Date: Wed, 20 Jul 2022 20:39:09 +0000 (+0300) Subject: More std::jthread X-Git-Url: https://git.stg.codes/stg.git/commitdiff_plain/479b8853c2ab18c98926a9369a03888021e9b986?ds=inline;hp=--cc More std::jthread --- 479b8853c2ab18c98926a9369a03888021e9b986 diff --git a/projects/sgconf/action.h b/projects/sgconf/action.h index 940ea7f6..bd3555ed 100644 --- a/projects/sgconf/action.h +++ b/projects/sgconf/action.h @@ -18,8 +18,7 @@ * Author : Maxim Mamontov <faust@stargazer.dp.ua> */ -#ifndef __STG_SGCONF_ACTION_H__ -#define __STG_SGCONF_ACTION_H__ +#pragma once #include <string> #include <map> @@ -37,21 +36,17 @@ class ACTION public: virtual ~ACTION() {} - virtual ACTION * Clone() const = 0; virtual std::string ParamDescription() const = 0; virtual std::string DefaultDescription() const = 0; virtual OPTION_BLOCK & Suboptions() = 0; virtual PARSER_STATE Parse(int argc, char ** argv, void * data = NULL) = 0; virtual void ParseValue(const std::string &) {} - class ERROR : public std::runtime_error + struct ERROR : std::runtime_error { - public: - ERROR(const std::string & message) - : std::runtime_error(message.c_str()) {} + explicit ERROR(const std::string & message) + : std::runtime_error(message.c_str()) {} }; }; } // namespace SGCONF - -#endif diff --git a/projects/sgconf/actions.h b/projects/sgconf/actions.h index 3181a105..f23e566d 100644 --- a/projects/sgconf/actions.h +++ b/projects/sgconf/actions.h @@ -40,17 +40,15 @@ template <typename F> class FUNC0_ACTION : public ACTION { public: - FUNC0_ACTION(const F & func) : m_func(func) {} + explicit FUNC0_ACTION(const F & func) : m_func(func) {} - virtual ACTION * Clone() const { return new FUNC0_ACTION<F>(*this); } - - virtual std::string ParamDescription() const { return ""; } - virtual std::string DefaultDescription() const { return ""; } - virtual OPTION_BLOCK & Suboptions() { return m_suboptions; } - virtual PARSER_STATE Parse(int argc, char ** argv, void * /*data*/) + std::string ParamDescription() const override { return ""; } + std::string DefaultDescription() const override { return ""; } + OPTION_BLOCK & Suboptions() override { return m_suboptions; } + PARSER_STATE Parse(int argc, char ** argv, void * /*data*/) override { - m_func(); - return PARSER_STATE(true, argc, argv); + m_func(); + return PARSER_STATE(true, argc, argv); } private: @@ -60,9 +58,9 @@ class FUNC0_ACTION : public ACTION template <typename F> inline -FUNC0_ACTION<F> * MakeFunc0Action(F func) +std::unique_ptr<ACTION> MakeFunc0Action(F func) { -return new FUNC0_ACTION<F>(func); +return std::make_unique<FUNC0_ACTION<F>>(func); } template <typename T> @@ -77,7 +75,7 @@ class PARAM_ACTION : public ACTION m_description(paramDescription), m_hasDefault(true) {} - PARAM_ACTION(STG::Optional<T> & param) + explicit PARAM_ACTION(STG::Optional<T> & param) : m_param(param), m_hasDefault(false) {} @@ -88,13 +86,11 @@ class PARAM_ACTION : public ACTION m_hasDefault(false) {} - virtual ACTION * Clone() const { return new PARAM_ACTION<T>(*this); } - - virtual std::string ParamDescription() const { return m_description; } - virtual std::string DefaultDescription() const; - virtual OPTION_BLOCK & Suboptions() { return m_suboptions; } - virtual PARSER_STATE Parse(int argc, char ** argv, void * /*data*/); - virtual void ParseValue(const std::string & value); + std::string ParamDescription() const override { return m_description; } + std::string DefaultDescription() const override; + OPTION_BLOCK & Suboptions() override { return m_suboptions; } + PARSER_STATE Parse(int argc, char ** argv, void * /*data*/) override; + void ParseValue(const std::string & value) override; private: STG::Optional<T> & m_param; @@ -176,26 +172,26 @@ return PARSER_STATE(false, --argc, ++argv); template <typename T> inline -PARAM_ACTION<T> * MakeParamAction(STG::Optional<T> & param, - const T & defaultValue, - const std::string & paramDescription) +std::unique_ptr<ACTION> MakeParamAction(STG::Optional<T> & param, + const T & defaultValue, + const std::string & paramDescription) { -return new PARAM_ACTION<T>(param, defaultValue, paramDescription); +return std::make_unique<PARAM_ACTION<T>>(param, defaultValue, paramDescription); } template <typename T> inline -PARAM_ACTION<T> * MakeParamAction(STG::Optional<T> & param) +std::unique_ptr<ACTION> MakeParamAction(STG::Optional<T> & param) { -return new PARAM_ACTION<T>(param); +return std::make_unique<PARAM_ACTION<T>>(param); } template <typename T> inline -PARAM_ACTION<T> * MakeParamAction(STG::Optional<T> & param, - const std::string & paramDescription) +std::unique_ptr<ACTION> MakeParamAction(STG::Optional<T> & param, + const std::string & paramDescription) { -return new PARAM_ACTION<T>(param, paramDescription); +return std::make_unique<PARAM_ACTION<T>>(param, paramDescription); } class KV_ACTION : public ACTION @@ -207,12 +203,10 @@ class KV_ACTION : public ACTION m_description(paramDescription) {} - virtual ACTION * Clone() const { return new KV_ACTION(*this); } - - virtual std::string ParamDescription() const { return m_description; } - virtual std::string DefaultDescription() const { return ""; } - virtual OPTION_BLOCK & Suboptions() { return m_suboptions; } - virtual PARSER_STATE Parse(int argc, char ** argv, void * data); + std::string ParamDescription() const override { return m_description; } + std::string DefaultDescription() const override { return ""; } + OPTION_BLOCK & Suboptions() override { return m_suboptions; } + PARSER_STATE Parse(int argc, char ** argv, void * data) override; private: std::string m_name; @@ -234,10 +228,10 @@ return PARSER_STATE(false, --argc, ++argv); } inline -KV_ACTION * MakeKVAction(const std::string & name, - const std::string & paramDescription) +std::unique_ptr<ACTION> MakeKVAction(const std::string & name, + const std::string & paramDescription) { -return new KV_ACTION(name, paramDescription); +return std::make_unique<KV_ACTION>(name, paramDescription); } } // namespace SGCONF diff --git a/projects/sgconf/api_action.h b/projects/sgconf/api_action.h index f27715ca..7fc22bca 100644 --- a/projects/sgconf/api_action.h +++ b/projects/sgconf/api_action.h @@ -90,12 +90,10 @@ class API_ACTION : public ACTION m_funPtr(funPtr) {} - virtual ACTION * Clone() const { return new API_ACTION(*this); } - - virtual std::string ParamDescription() const { return m_description; } - virtual std::string DefaultDescription() const { return ""; } - virtual OPTION_BLOCK & Suboptions() { return m_suboptions; } - virtual PARSER_STATE Parse(int argc, char ** argv, void * /*data*/); + std::string ParamDescription() const override { return m_description; } + std::string DefaultDescription() const override { return ""; } + OPTION_BLOCK & Suboptions() override { return m_suboptions; } + PARSER_STATE Parse(int argc, char ** argv, void * /*data*/) override; private: COMMANDS & m_commands; @@ -107,35 +105,35 @@ class API_ACTION : public ACTION }; inline -ACTION * MakeAPIAction(COMMANDS & commands, +std::unique_ptr<ACTION> MakeAPIAction(COMMANDS & commands, const std::string & paramDescription, const std::vector<API_ACTION::PARAM> & params, API_FUNCTION funPtr) { -return new API_ACTION(commands, paramDescription, true, params, funPtr); +return std::make_unique<API_ACTION>(commands, paramDescription, true, params, funPtr); } inline -ACTION * MakeAPIAction(COMMANDS & commands, +std::unique_ptr<ACTION> MakeAPIAction(COMMANDS & commands, const std::vector<API_ACTION::PARAM> & params, API_FUNCTION funPtr) { -return new API_ACTION(commands, "", false, params, funPtr); +return std::make_unique<API_ACTION>(commands, "", false, params, funPtr); } inline -ACTION * MakeAPIAction(COMMANDS & commands, +std::unique_ptr<ACTION> MakeAPIAction(COMMANDS & commands, const std::string & paramDescription, API_FUNCTION funPtr) { -return new API_ACTION(commands, paramDescription, true, funPtr); +return std::make_unique<API_ACTION>(commands, paramDescription, true, funPtr); } inline -ACTION * MakeAPIAction(COMMANDS & commands, +std::unique_ptr<ACTION> MakeAPIAction(COMMANDS & commands, API_FUNCTION funPtr) { -return new API_ACTION(commands, "", false, funPtr); +return std::make_unique<API_ACTION>(commands, "", false, funPtr); } } diff --git a/projects/sgconf/main.cpp b/projects/sgconf/main.cpp index 97908195..3413dbd9 100644 --- a/projects/sgconf/main.cpp +++ b/projects/sgconf/main.cpp @@ -73,7 +73,7 @@ template <typename A, typename R> class FUNC1_ADAPTER : public std::unary_function<A, R> { public: - FUNC1_ADAPTER(R (*func)(A)) : m_func(func) {} + explicit FUNC1_ADAPTER(R (*func)(A)) : m_func(func) {} const R operator()(A arg) const { return (m_func)(arg); } private: R (*m_func)(A); @@ -160,12 +160,10 @@ class CONFIG_ACTION : public ACTION m_description(paramDescription) {} - virtual ACTION * Clone() const { return new CONFIG_ACTION(*this); } - - virtual std::string ParamDescription() const { return m_description; } - virtual std::string DefaultDescription() const { return ""; } - virtual OPTION_BLOCK & Suboptions() { return m_suboptions; } - virtual PARSER_STATE Parse(int argc, char ** argv, void * /*data*/); + std::string ParamDescription() const override { return m_description; } + std::string DefaultDescription() const override { return ""; } + OPTION_BLOCK & Suboptions() override { return m_suboptions; } + PARSER_STATE Parse(int argc, char ** argv, void * /*data*/) override; private: SGCONF::CONFIG & m_config; @@ -227,11 +225,10 @@ else } } -inline -CONFIG_ACTION * MakeParamAction(SGCONF::CONFIG & config, - const std::string & paramDescription) +std::unique_ptr<SGCONF::ACTION> MakeParamAction(SGCONF::CONFIG & config, + const std::string & paramDescription) { -return new CONFIG_ACTION(config, paramDescription); +return std::make_unique<CONFIG_ACTION>(config, paramDescription); } } // namespace SGCONF diff --git a/projects/sgconf/options.cpp b/projects/sgconf/options.cpp index e431bcb0..06378d1c 100644 --- a/projects/sgconf/options.cpp +++ b/projects/sgconf/options.cpp @@ -39,26 +39,26 @@ namespace template <class C> void ReadConfigFile(const std::string & filePath, void (C::* callback)(const std::string&, const std::string&), C * obj) { -std::ifstream stream(filePath.c_str()); -std::string line; -size_t num = 0; -while (std::getline(stream, line)) + std::ifstream stream(filePath.c_str()); + std::string line; + size_t num = 0; + while (std::getline(stream, line)) { - ++num; - line = Trim(line); - std::string::size_type pos = line.find_first_of('#'); - if (pos != std::string::npos) - line = line.substr(0, pos); - if (line.empty()) - continue; - pos = line.find_first_of('='); - if (pos == std::string::npos) + ++num; + line = Trim(line); + std::string::size_type pos = line.find_first_of('#'); + if (pos != std::string::npos) + line = line.substr(0, pos); + if (line.empty()) + continue; + pos = line.find_first_of('='); + if (pos == std::string::npos) { - std::ostringstream error; - error << "Bad file format, missing '=' in '" << filePath << ":" << num << "'."; - throw std::runtime_error(error.str().c_str()); + std::ostringstream error; + error << "Bad file format, missing '=' in '" << filePath << ":" << num << "'."; + throw std::runtime_error(error.str().c_str()); } - (obj->*callback)(Trim(line.substr(0, pos)), Trim(line.substr(pos + 1, line.length() - pos - 1))); + (obj->*callback)(Trim(line.substr(0, pos)), Trim(line.substr(pos + 1, line.length() - pos - 1))); } } @@ -72,184 +72,157 @@ using SGCONF::PARSER_STATE; OPTION::OPTION(const std::string & shortName, const std::string & longName, - ACTION * action, + std::unique_ptr<ACTION> action, const std::string & description) : m_shortName(shortName), m_longName(longName), - m_action(action), + m_action(std::move(action)), m_description(description) { } OPTION::OPTION(const std::string & longName, - ACTION * action, + std::unique_ptr<ACTION> action, const std::string & description) : m_longName(longName), - m_action(action), + m_action(std::move(action)), m_description(description) { } -OPTION::OPTION(const OPTION & rhs) - : m_shortName(rhs.m_shortName), - m_longName(rhs.m_longName), - m_action(rhs.m_action->Clone()), - m_description(rhs.m_description) -{ -} - -OPTION::~OPTION() -{ -delete m_action; -} - -OPTION & OPTION::operator=(const OPTION & rhs) -{ -m_shortName = rhs.m_shortName; -m_longName = rhs.m_longName; -m_action = rhs.m_action->Clone(); -m_description = rhs.m_description; -return *this; -} - void OPTION::Help(size_t level) const { -if (!m_action) - throw ERROR("Option is not defined."); -std::string indent(level, '\t'); -std::cout << indent; -if (!m_shortName.empty()) - std::cout << "-" << m_shortName << ", "; -std::cout << "--" << m_longName << " " << m_action->ParamDescription() - << "\t" << m_description << m_action->DefaultDescription() << "\n"; -m_action->Suboptions().Help(level); + if (!m_action) + throw ERROR("Option is not defined."); + std::string indent(level, '\t'); + std::cout << indent; + if (!m_shortName.empty()) + std::cout << "-" << m_shortName << ", "; + std::cout << "--" << m_longName << " " << m_action->ParamDescription() + << "\t" << m_description << m_action->DefaultDescription() << "\n"; + m_action->Suboptions().Help(level); } bool OPTION::Check(const char * arg) const { -if (arg == NULL) - return false; + if (arg == NULL) + return false; -if (*arg++ != '-') - return false; + if (*arg++ != '-') + return false; -if (*arg == '-') -{ - return m_longName == arg + 1; -} + if (*arg == '-') + return m_longName == arg + 1; -return m_shortName == arg; + return m_shortName == arg; } PARSER_STATE OPTION::Parse(int argc, char ** argv, void * data) { -if (!m_action) - throw ERROR("Option is not defined."); -try + if (!m_action) + throw ERROR("Option is not defined."); + try { - return m_action->Parse(argc, argv, data); + return m_action->Parse(argc, argv, data); } -catch (const ACTION::ERROR & ex) + catch (const ACTION::ERROR & ex) { - if (m_longName.empty()) - throw ERROR("-" + m_shortName + ": " + ex.what()); - else - throw m_shortName.empty() ? ERROR("--" + m_longName + ": " + ex.what()) - : ERROR("--" + m_longName + ", -" + m_shortName + ": " + ex.what()); + if (m_longName.empty()) + throw ERROR("-" + m_shortName + ": " + ex.what()); + else + throw m_shortName.empty() ? ERROR("--" + m_longName + ": " + ex.what()) + : ERROR("--" + m_longName + ", -" + m_shortName + ": " + ex.what()); } } void OPTION::ParseValue(const std::string & value) { -if (!m_action) - throw ERROR("Option is not defined."); -try + if (!m_action) + throw ERROR("Option is not defined."); + try { - return m_action->ParseValue(value); + return m_action->ParseValue(value); } -catch (const ACTION::ERROR & ex) + catch (const ACTION::ERROR & ex) { - throw ERROR(m_longName + ": " + ex.what()); + throw ERROR(m_longName + ": " + ex.what()); } } OPTION_BLOCK & OPTION_BLOCK::Add(const std::string & shortName, const std::string & longName, - ACTION * action, + std::unique_ptr<ACTION> action, const std::string & description) { -m_options.push_back(OPTION(shortName, longName, action, description)); -return *this; + m_options.emplace_back(shortName, longName, std::move(action), description); + return *this; } OPTION_BLOCK & OPTION_BLOCK::Add(const std::string & longName, - ACTION * action, + std::unique_ptr<ACTION> action, const std::string & description) { -m_options.push_back(OPTION(longName, action, description)); -return *this; + m_options.emplace_back(longName, std::move(action), description); + return *this; } void OPTION_BLOCK::Help(size_t level) const { -if (m_options.empty()) - return; -if (!m_description.empty()) - std::cout << m_description << ":\n"; -std::for_each(m_options.begin(), - m_options.end(), - [&level](const auto& opt){ opt.Help(level + 1); }); + if (m_options.empty()) + return; + if (!m_description.empty()) + std::cout << m_description << ":\n"; + for (const auto& option : m_options) + option.Help(level + 1); } PARSER_STATE OPTION_BLOCK::Parse(int argc, char ** argv, void * data) { -PARSER_STATE state(false, argc, argv); -if (state.argc == 0) - return state; -while (state.argc > 0 && !state.stop) + PARSER_STATE state(false, argc, argv); + if (state.argc == 0) + return state; + while (state.argc > 0 && !state.stop) { - const auto it = std::find_if(m_options.begin(), m_options.end(), [&state](const auto& opt){ return opt.Check(*state.argv); }); - if (it != m_options.end()) - state = it->Parse(--state.argc, ++state.argv, data); - else - break; + const auto it = std::find_if(m_options.begin(), m_options.end(), [&state](const auto& opt){ return opt.Check(*state.argv); }); + if (it != m_options.end()) + state = it->Parse(--state.argc, ++state.argv, data); + else + break; } -return state; + return state; } void OPTION_BLOCK::ParseFile(const std::string & filePath) { -if (access(filePath.c_str(), R_OK)) - throw ERROR("File '" + filePath + "' does not exists."); -ReadConfigFile(filePath, &OPTION_BLOCK::OptionCallback, this); + if (access(filePath.c_str(), R_OK)) + throw ERROR("File '" + filePath + "' does not exists."); + ReadConfigFile(filePath, &OPTION_BLOCK::OptionCallback, this); } void OPTION_BLOCK::OptionCallback(const std::string & key, const std::string & value) { -for (std::vector<OPTION>::iterator it = m_options.begin(); it != m_options.end(); ++it) - if (it->Name() == key) - it->ParseValue(value); + for (auto& option : m_options) + if (option.Name() == key) + option.ParseValue(value); } void OPTION_BLOCKS::Help(size_t level) const { -std::list<OPTION_BLOCK>::const_iterator it(m_blocks.begin()); -while (it != m_blocks.end()) + for (const auto& block : m_blocks) { - it->Help(level); - std::cout << "\n"; - ++it; + block.Help(level); + std::cout << "\n"; } } PARSER_STATE OPTION_BLOCKS::Parse(int argc, char ** argv) { -PARSER_STATE state(false, argc, argv); -std::list<OPTION_BLOCK>::iterator it(m_blocks.begin()); -while (state.argc > 0 && !state.stop && it != m_blocks.end()) + PARSER_STATE state(false, argc, argv); + auto it = m_blocks.begin(); + while (state.argc > 0 && !state.stop && it != m_blocks.end()) { - state = it->Parse(state.argc, state.argv); - ++it; + state = it->Parse(state.argc, state.argv); + ++it; } -return state; + return state; } diff --git a/projects/sgconf/options.h b/projects/sgconf/options.h index c00707bf..012b5167 100644 --- a/projects/sgconf/options.h +++ b/projects/sgconf/options.h @@ -18,14 +18,13 @@ * Author : Maxim Mamontov <faust@stargazer.dp.ua> */ -#ifndef __STG_SGCONF_OPTIONS_H__ -#define __STG_SGCONF_OPTIONS_H__ +#pragma once #include <string> #include <vector> -#include <list> #include <utility> #include <stdexcept> +#include <memory> #include <cstddef> // size_t namespace SGCONF @@ -39,15 +38,14 @@ class OPTION public: OPTION(const std::string & shortName, const std::string & longName, - ACTION * action, + std::unique_ptr<ACTION> action, const std::string & description); OPTION(const std::string & longName, - ACTION * action, + std::unique_ptr<ACTION> action, const std::string & description); - OPTION(const OPTION & rhs); - ~OPTION(); - OPTION & operator=(const OPTION & rhs); + OPTION(OPTION&& rhs) = default; + OPTION& operator=(OPTION& rhs) = default; void Help(size_t level = 0) const; PARSER_STATE Parse(int argc, char ** argv, void * data); @@ -55,17 +53,16 @@ class OPTION bool Check(const char * arg) const; const std::string & Name() const { return m_longName; } - class ERROR : public std::runtime_error + struct ERROR : std::runtime_error { - public: - ERROR(const std::string & message) - : std::runtime_error(message.c_str()) {} + explicit ERROR(const std::string & message) + : std::runtime_error(message.c_str()) {} }; private: std::string m_shortName; std::string m_longName; - ACTION * m_action; + std::unique_ptr<ACTION> m_action; std::string m_description; }; @@ -73,14 +70,18 @@ class OPTION_BLOCK { public: OPTION_BLOCK() {} - OPTION_BLOCK(const std::string & description) + explicit OPTION_BLOCK(const std::string & description) : m_description(description) {} + + OPTION_BLOCK(OPTION_BLOCK&&) = default; + OPTION_BLOCK& operator=(OPTION_BLOCK&&) = default; + OPTION_BLOCK & Add(const std::string & shortName, const std::string & longName, - ACTION * action, + std::unique_ptr<ACTION> action, const std::string & description); OPTION_BLOCK & Add(const std::string & longName, - ACTION * action, + std::unique_ptr<ACTION> action, const std::string & description); void Help(size_t level) const; @@ -88,11 +89,10 @@ class OPTION_BLOCK PARSER_STATE Parse(int argc, char ** argv, void * data = NULL); void ParseFile(const std::string & filePath); - class ERROR : public std::runtime_error + struct ERROR : std::runtime_error { - public: - ERROR(const std::string & message) - : std::runtime_error(message.c_str()) {} + explicit ERROR(const std::string & message) + : std::runtime_error(message.c_str()) {} }; private: @@ -107,14 +107,12 @@ class OPTION_BLOCKS public: OPTION_BLOCK & Add(const std::string & description) { m_blocks.push_back(OPTION_BLOCK(description)); return m_blocks.back(); } - void Add(const OPTION_BLOCK & block) { m_blocks.push_back(block); } + void Add(OPTION_BLOCK&& block) { m_blocks.push_back(std::move(block)); } void Help(size_t level) const; PARSER_STATE Parse(int argc, char ** argv); private: - std::list<OPTION_BLOCK> m_blocks; + std::vector<OPTION_BLOCK> m_blocks; }; } // namespace SGCONF - -#endif diff --git a/projects/stargazer/actions.h b/projects/stargazer/actions.h index 33c9a8fd..360a56e1 100644 --- a/projects/stargazer/actions.h +++ b/projects/stargazer/actions.h @@ -1,5 +1,4 @@ -#ifndef __ACTIONS_H__ -#define __ACTIONS_H__ +#pragma once // Usage: // @@ -21,7 +20,7 @@ template <class ACTIVE_CLASS, typename DATA_TYPE> struct ACTOR { -typedef void (ACTIVE_CLASS::*TYPE)(DATA_TYPE); + using TYPE = void (ACTIVE_CLASS::*)(DATA_TYPE); }; // Abstract base action class for polymorphic action invocation @@ -34,15 +33,17 @@ public: // Concrete generalized action type - an actor with it's data and owner template <class ACTIVE_CLASS, typename DATA_TYPE> -class ACTION : public BASE_ACTION, - public std::unary_function<ACTIVE_CLASS &, void> +class ACTION : public BASE_ACTION { public: ACTION(ACTIVE_CLASS & ac, typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a, DATA_TYPE d) : activeClass(ac), actor(a), data(d) {} - void Invoke() override; + void Invoke() override + { + (activeClass.*actor)(data); + } private: ACTION(const ACTION<ACTIVE_CLASS, DATA_TYPE> & rvalue); ACTION<ACTIVE_CLASS, DATA_TYPE> & operator=(const ACTION<ACTIVE_CLASS, DATA_TYPE> & rvalue); @@ -54,37 +55,42 @@ private: // A list of an actions // All methods are thread-safe -class ACTIONS_LIST : private std::vector<BASE_ACTION *> +class ACTIONS_LIST { public: - // Just a typedef for parent class - typedef std::vector<BASE_ACTION *> parent; + ~ACTIONS_LIST() + { + std::lock_guard lock(m_mutex); + for (auto action : m_list) + delete action; + } - // Initialize mutex - ACTIONS_LIST(); - // Delete actions and destroy mutex - virtual ~ACTIONS_LIST(); + auto begin() { std::lock_guard lock(m_mutex); return m_list.begin(); } + auto end() { std::lock_guard lock(m_mutex); return m_list.end(); } + auto begin() const { std::lock_guard lock(m_mutex); return m_list.begin(); } + auto end() const { std::lock_guard lock(m_mutex); return m_list.end(); } - parent::iterator begin(); - parent::iterator end(); - parent::const_iterator begin() const; - parent::const_iterator end() const; - - bool empty() const; - size_t size() const; - void swap(ACTIONS_LIST & list); + bool empty() const { std::lock_guard lock(m_mutex); return m_list.empty(); } + size_t size() const { std::lock_guard lock(m_mutex); return m_list.size(); } + void swap(ACTIONS_LIST & rhs) { std::lock_guard lock(m_mutex); m_list.swap(rhs.m_list); } // Add an action to list template <class ACTIVE_CLASS, typename DATA_TYPE> void Enqueue(ACTIVE_CLASS & ac, typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a, - DATA_TYPE d); + DATA_TYPE d) + { + std::lock_guard lock(m_mutex); + m_list.push_back(new ACTION<ACTIVE_CLASS, DATA_TYPE>(ac, a, d)); + } // Invoke all actions in the list - void InvokeAll(); + void InvokeAll() + { + std::lock_guard lock(m_mutex); + for (auto action : m_list) + action->Invoke(); + } private: mutable std::mutex m_mutex; + std::vector<BASE_ACTION*> m_list; }; - -#include "actions.inl.h" - -#endif diff --git a/projects/stargazer/actions.inl.h b/projects/stargazer/actions.inl.h deleted file mode 100644 index 7a0bac35..00000000 --- a/projects/stargazer/actions.inl.h +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef __ACTIONS_INL_H__ -#define __ACTIONS_INL_H__ - -#include <algorithm> - -#include "stg/locker.h" - -// Polymorphick action invocation -template <class ACTIVE_CLASS, typename DATA_TYPE> -inline -void ACTION<ACTIVE_CLASS, DATA_TYPE>::Invoke() -{ -(activeClass.*actor)(data); -} - -inline -ACTIONS_LIST::ACTIONS_LIST() -{ -} - -// Delete all actions before deleting list -inline -ACTIONS_LIST::~ACTIONS_LIST() -{ -std::lock_guard lock(m_mutex); - -parent::iterator it(parent::begin()); -while (it != parent::end()) - delete *it++; -} - -inline -ACTIONS_LIST::parent::iterator ACTIONS_LIST::begin() -{ -std::lock_guard lock(m_mutex); -return parent::begin(); -} - -inline -ACTIONS_LIST::parent::iterator ACTIONS_LIST::end() -{ -std::lock_guard lock(m_mutex); -return parent::end(); -} - -inline -ACTIONS_LIST::parent::const_iterator ACTIONS_LIST::begin() const -{ -std::lock_guard lock(m_mutex); -return parent::begin(); -} - -inline -ACTIONS_LIST::parent::const_iterator ACTIONS_LIST::end() const -{ -std::lock_guard lock(m_mutex); -return parent::end(); -} - -inline -bool ACTIONS_LIST::empty() const -{ -std::lock_guard lock(m_mutex); -return parent::empty(); -} - -inline -size_t ACTIONS_LIST::size() const -{ -std::lock_guard lock(m_mutex); -return parent::size(); -} - -inline -void ACTIONS_LIST::swap(ACTIONS_LIST & list) -{ -std::lock_guard lock(m_mutex); -parent::swap(list); -} - -template <class ACTIVE_CLASS, typename DATA_TYPE> -inline -void ACTIONS_LIST::Enqueue(ACTIVE_CLASS & ac, - typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a, - DATA_TYPE d) -{ -std::lock_guard lock(m_mutex); -push_back(new ACTION<ACTIVE_CLASS, DATA_TYPE>(ac, a, d)); -} - -inline -void ACTIONS_LIST::InvokeAll() -{ -std::lock_guard lock(m_mutex); -std::for_each( - parent::begin(), - parent::end(), - [](auto action){ action->Invoke(); }); -} - -#endif diff --git a/projects/stargazer/eventloop.cpp b/projects/stargazer/eventloop.cpp index 36a77e9e..ea175c41 100644 --- a/projects/stargazer/eventloop.cpp +++ b/projects/stargazer/eventloop.cpp @@ -1,119 +1,59 @@ -#include <csignal> -#include <cerrno> -#include <cstring> - -#include "stg/locker.h" #include "stg/common.h" #include "eventloop.h" -EVENT_LOOP::EVENT_LOOP() - : ACTIONS_LIST(), - _running(false), - _stopped(true), - _tid(), - _mutex(), - _condition() -{ -pthread_mutex_init(&_mutex, NULL); -pthread_cond_init(&_condition, NULL); -} +#include <csignal> +#include <cerrno> +#include <cstring> -EVENT_LOOP::~EVENT_LOOP() +EVENT_LOOP& EVENT_LOOP::instance() { -pthread_cond_destroy(&_condition); -pthread_mutex_destroy(&_mutex); + static EVENT_LOOP el; + return el; } bool EVENT_LOOP::Start() { -_running = true; -if (pthread_create(&_tid, NULL, Run, this)) - { - printfd(__FILE__, "EVENT_LOOP::Start - Failed to create thread: '%s'\n", strerror(errno)); - return true; - } +m_thread = std::jthread([this](auto token){ Run(std::move(token)); }); return false; } bool EVENT_LOOP::Stop() { -_running = false; +m_thread.request_stop(); // Wake up thread -pthread_cond_signal(&_condition); -// Wait until thread exit -pthread_join(_tid, NULL); +m_cond.notify_all(); +m_thread.join(); return false; } -void * EVENT_LOOP::Run(void * self) -{ -EVENT_LOOP * ev = static_cast<EVENT_LOOP *>(self); -ev->Runner(); -return NULL; -} - -void EVENT_LOOP::Runner() +void EVENT_LOOP::Run(std::stop_token token) { sigset_t signalSet; sigfillset(&signalSet); pthread_sigmask(SIG_BLOCK, &signalSet, NULL); -_stopped = false; printfd(__FILE__, "EVENT_LOOP::Runner - Before start\n"); -while (_running) +while (!token.stop_requested()) { + // Create new empty actions list + ACTIONS_LIST local; { - STG_LOCKER lock(&_mutex); + std::unique_lock lock(m_mutex); // Check for any actions... - if (empty()) - { - // ... and sleep until new actions added - printfd(__FILE__, "EVENT_LOOP::Runner - Sleeping until new actions arrived\n"); - pthread_cond_wait(&_condition, &_mutex); - } + // ... and sleep until new actions added + printfd(__FILE__, "EVENT_LOOP::Runner - Sleeping until new actions arrived\n"); + m_cond.wait(lock); // Check for running after wake up - if (!_running) - { - // Don't process any actions if stopping - break; - } + if (token.stop_requested()) + break; // Don't process any actions if stopping + if (!m_list.empty()) + local.swap(m_list); } - // Create new empty actions list - ACTIONS_LIST local; // Fast swap with current - swap(local); + m_list.swap(local); // Invoke all current actions printfd(__FILE__, "EVENT_LOOP::Runner - Invoke %d actions\n", local.size()); local.InvokeAll(); } printfd(__FILE__, "EVENT_LOOP::Runner - Before stop\n"); -_stopped = true; -} - -namespace { - -pthread_mutex_t singletonMutex; - -} - -EVENT_LOOP & EVENT_LOOP_SINGLETON::GetInstance() -{ -// Double-checking technique -if (!_instance) - { - STG_LOCKER lock(&singletonMutex); - if (!_instance) - { - CreateInstance(); - } - } -return *_instance; } - -void EVENT_LOOP_SINGLETON::CreateInstance() -{ -static EVENT_LOOP loop; -_instance = &loop; -} - -EVENT_LOOP * EVENT_LOOP_SINGLETON::_instance = NULL; diff --git a/projects/stargazer/eventloop.h b/projects/stargazer/eventloop.h index 0e798142..0b2b8397 100644 --- a/projects/stargazer/eventloop.h +++ b/projects/stargazer/eventloop.h @@ -1,63 +1,45 @@ #ifndef __EVENT_LOOP_H__ #define __EVENT_LOOP_H__ -#include <pthread.h> - -#include "stg/noncopyable.h" #include "actions.h" -class EVENT_LOOP : private NONCOPYABLE, - private ACTIONS_LIST +#include <mutex> +#include <condition_variable> +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#include <jthread.hpp> +#pragma GCC diagnostic pop + +class EVENT_LOOP { public: + static EVENT_LOOP& instance(); + bool Start(); bool Stop(); - bool IsRunning() const { return _running; } template <class ACTIVE_CLASS, typename DATA_TYPE> void Enqueue(ACTIVE_CLASS & ac, typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a, - DATA_TYPE d); + DATA_TYPE d) + { + std::lock_guard lock(m_mutex); + // Add new action + m_list.Enqueue(ac, a, d); + // Signal about new action + m_cond.notify_all(); + } private: - bool _running; - bool _stopped; - pthread_t _tid; - pthread_mutex_t _mutex; - pthread_cond_t _condition; - - EVENT_LOOP(); - virtual ~EVENT_LOOP(); - - static void * Run(void *); - void Runner(); - - friend class EVENT_LOOP_SINGLETON; -}; + std::jthread m_thread; + std::mutex m_mutex; + std::condition_variable m_cond; -class EVENT_LOOP_SINGLETON : private NONCOPYABLE -{ - public: - static EVENT_LOOP & GetInstance(); + ACTIONS_LIST m_list; - private: - static EVENT_LOOP * _instance; - static void CreateInstance(); + EVENT_LOOP() = default; - EVENT_LOOP_SINGLETON() {} - ~EVENT_LOOP_SINGLETON() {} + void Run(std::stop_token token); }; -template <class ACTIVE_CLASS, typename DATA_TYPE> -void EVENT_LOOP::Enqueue(ACTIVE_CLASS & ac, - typename ACTOR<ACTIVE_CLASS, DATA_TYPE>::TYPE a, - DATA_TYPE d) -{ -STG_LOCKER lock(&_mutex); -// Add new action -ACTIONS_LIST::Enqueue(ac, a, d); -// Signal about new action -pthread_cond_signal(&_condition); -} - #endif diff --git a/projects/stargazer/main.cpp b/projects/stargazer/main.cpp index d70f50a3..bcf7af77 100644 --- a/projects/stargazer/main.cpp +++ b/projects/stargazer/main.cpp @@ -282,7 +282,7 @@ int main(int argc, char* argv[]) return -1; } - auto& loop = EVENT_LOOP_SINGLETON::GetInstance(); + auto& loop = EVENT_LOOP::instance(); StoreLoader storeLoader(settings); if (storeLoader.load()) diff --git a/projects/stargazer/plugins/capture/ether_freebsd/ether_cap.cpp b/projects/stargazer/plugins/capture/ether_freebsd/ether_cap.cpp index f063da9f..aa10327c 100644 --- a/projects/stargazer/plugins/capture/ether_freebsd/ether_cap.cpp +++ b/projects/stargazer/plugins/capture/ether_freebsd/ether_cap.cpp @@ -108,8 +108,7 @@ return "cap_bpf v.1.0"; } //----------------------------------------------------------------------------- BPF_CAP::BPF_CAP() - : nonstop(false), - isRunning(false), + : isRunning(false), capSock(-1), traffCnt(NULL), logger(STG::PluginLogger::get("cap_bpf")) @@ -138,15 +137,7 @@ if (BPFCapOpen() < 0) return -1; } -nonstop = true; - -if (pthread_create(&thread, NULL, Run, this)) - { - errorStr = "Cannot create thread."; - logger("Cannot create thread."); - printfd(__FILE__, "Cannot create thread\n"); - return -1; - } +m_thread = std::jthread([this](auto token){ Run(std::move(token)); }); return 0; } @@ -158,7 +149,7 @@ if (!isRunning) BPFCapClose(); -nonstop = false; +m_thread.request_stop(); //5 seconds to thread stops itself int i; @@ -173,28 +164,20 @@ for (i = 0; i < 25; i++) //after 5 seconds waiting thread still running. now killing it if (isRunning) - { - //TODO pthread_cancel() - if (pthread_kill(thread, SIGINT)) - { - errorStr = "Cannot kill thread."; - logger("Cannot send signal to thread."); - printfd(__FILE__, "Cannot kill thread\n"); - return -1; - } - } + m_thread.detach(); +else + m_thread.join(); return 0; } //----------------------------------------------------------------------------- -void * BPF_CAP::Run(void * d) +void BPF_CAP::Run(std::stop_token token) { sigset_t signalSet; sigfillset(&signalSet); pthread_sigmask(SIG_BLOCK, &signalSet, NULL); -BPF_CAP * dc = static_cast<BPF_CAP *>(d); -dc->isRunning = true; +isRunning = true; uint8_t hdr[96]; //68 + 14 + 4(size) + 9(SYS_IFACE) + 1(align to 4) = 96 @@ -204,19 +187,18 @@ memset(hdr, 0, sizeof(hdr)); rpp->dataLen = -1; char * iface; -while (dc->nonstop) +while (!token.stop_requested()) { - if (dc->BPFCapRead((char*)&hdr, 68 + 14, &iface)) + if (BPFCapRead((char*)&hdr, 68 + 14, &iface)) continue; if (!(hdr[12] == 0x8 && hdr[13] == 0x0)) continue; - dc->traffCnt->process(*rpp); + traffCnt->process(*rpp); } -dc->isRunning = false; -return NULL; +isRunning = false; } //----------------------------------------------------------------------------- int BPF_CAP::BPFCapOpen() diff --git a/projects/stargazer/plugins/capture/ether_freebsd/ether_cap.h b/projects/stargazer/plugins/capture/ether_freebsd/ether_cap.h index 07380bda..a4167274 100644 --- a/projects/stargazer/plugins/capture/ether_freebsd/ether_cap.h +++ b/projects/stargazer/plugins/capture/ether_freebsd/ether_cap.h @@ -32,9 +32,12 @@ #include <string> #include <vector> +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#include <jthread.hpp> +#pragma GCC diagnostic pop #include <cstdint> -#include <pthread.h> #include <sys/poll.h> #define BUFF_LEN (128) @@ -114,7 +117,7 @@ private: BPF_CAP(const BPF_CAP & rvalue); BPF_CAP & operator=(const BPF_CAP & rvalue); - static void * Run(void *); + void Run(std::stop_token token); int BPFCapOpen(); int BPFCapOpen(BPF_DATA * bd); int BPFCapClose(); @@ -128,8 +131,7 @@ private: std::vector<BPF_DATA> bpfData; std::vector<pollfd> polld; - pthread_t thread; - bool nonstop; + std::jthread m_thread; bool isRunning; int capSock; STG::ModuleSettings settings; diff --git a/projects/stargazer/plugins/capture/ether_linux/ether_cap.cpp b/projects/stargazer/plugins/capture/ether_linux/ether_cap.cpp index 7ca6c01f..3ac60d1f 100644 --- a/projects/stargazer/plugins/capture/ether_linux/ether_cap.cpp +++ b/projects/stargazer/plugins/capture/ether_linux/ether_cap.cpp @@ -65,8 +65,7 @@ return "cap_ether v.1.2"; } //----------------------------------------------------------------------------- ETHER_CAP::ETHER_CAP() - : nonstop(false), - isRunning(false), + : isRunning(false), capSock(-1), traffCnt(NULL), logger(STG::PluginLogger::get("cap_ether")) @@ -85,15 +84,7 @@ if (EthCapOpen() < 0) return -1; } -nonstop = true; - -if (pthread_create(&thread, NULL, Run, this)) - { - errorStr = "Cannot create thread."; - logger("Cannot create thread."); - printfd(__FILE__, "Cannot create thread\n"); - return -1; - } +m_thread = std::jthread([this](auto token){ Run(std::move(token)); }); return 0; } @@ -103,7 +94,7 @@ int ETHER_CAP::Stop() if (!isRunning) return 0; -nonstop = false; +m_thread.request_stop(); //5 seconds to thread stops itself for (int i = 0; i < 25 && isRunning; i++) @@ -113,43 +104,21 @@ for (int i = 0; i < 25 && isRunning; i++) } //after 5 seconds waiting thread still running. now killing it if (isRunning) - { - if (pthread_kill(thread, SIGUSR1)) - { - errorStr = "Cannot kill thread."; - logger("Cannot send signal to thread."); - return -1; - } - for (int i = 0; i < 25 && isRunning; ++i) - { - struct timespec ts = {0, 200000000}; - nanosleep(&ts, NULL); - } - if (isRunning) - { - errorStr = "ETHER_CAP not stopped."; - logger("Cannot stop thread."); - printfd(__FILE__, "Cannot stop thread\n"); - return -1; - } - else - { - pthread_join(thread, NULL); - } - } + m_thread.detach(); +else + m_thread.join(); EthCapClose(); return 0; } //----------------------------------------------------------------------------- -void * ETHER_CAP::Run(void * d) +void ETHER_CAP::Run(std::stop_token token) { sigset_t signalSet; sigfillset(&signalSet); pthread_sigmask(SIG_BLOCK, &signalSet, NULL); -ETHER_CAP * dc = static_cast<ETHER_CAP *>(d); -dc->isRunning = true; +isRunning = true; struct ETH_IP { @@ -168,9 +137,9 @@ ethIP->rp.dataLen = -1; char * iface = NULL; -while (dc->nonstop) +while (!token.stop_requested()) { - if (dc->EthCapRead(ðip, 68 + 14, &iface)) + if (EthCapRead(ðip, 68 + 14, &iface)) { continue; } @@ -178,11 +147,10 @@ while (dc->nonstop) if (ethIP->ethHdr[7] != 0x8) continue; - dc->traffCnt->process(ethIP->rp); + traffCnt->process(ethIP->rp); } -dc->isRunning = false; -return NULL; +isRunning = false; } //----------------------------------------------------------------------------- int ETHER_CAP::EthCapOpen() @@ -202,7 +170,7 @@ return 0; int ETHER_CAP::EthCapRead(void * buffer, int blen, char **) { struct sockaddr_ll addr; -int addrLen; +socklen_t addrLen; if (!WaitPackets(capSock)) { @@ -211,7 +179,7 @@ if (!WaitPackets(capSock)) addrLen = sizeof(addr); -if (recvfrom(capSock, ((char*)buffer) + 2, blen, 0, (struct sockaddr *)&addr, (socklen_t*)&addrLen) < 0) +if (recvfrom(capSock, static_cast<char*>(buffer) + 2, blen, 0, reinterpret_cast<sockaddr *>(&addr), &addrLen) < 0) { logger("recvfrom error: %s", strerror(errno)); return ENODATA; diff --git a/projects/stargazer/plugins/capture/ether_linux/ether_cap.h b/projects/stargazer/plugins/capture/ether_linux/ether_cap.h index cf776a45..d50923d6 100644 --- a/projects/stargazer/plugins/capture/ether_linux/ether_cap.h +++ b/projects/stargazer/plugins/capture/ether_linux/ether_cap.h @@ -25,14 +25,16 @@ #pragma once -#include <pthread.h> - -#include <string> - #include "stg/plugin.h" #include "stg/module_settings.h" #include "stg/logger.h" +#include <string> +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#include <jthread.hpp> +#pragma GCC diagnostic pop + namespace STG { @@ -66,15 +68,14 @@ private: ETHER_CAP(const ETHER_CAP & rvalue); ETHER_CAP & operator=(const ETHER_CAP & rvalue); - static void * Run(void *); + void Run(std::stop_token token); int EthCapOpen(); int EthCapClose(); int EthCapRead(void * buffer, int blen, char ** iface); mutable std::string errorStr; - pthread_t thread; - bool nonstop; + std::jthread m_thread; bool isRunning; int capSock; diff --git a/projects/stargazer/plugins/capture/nfqueue/nfqueue.cpp b/projects/stargazer/plugins/capture/nfqueue/nfqueue.cpp index 3c79c1b1..0a5d8712 100644 --- a/projects/stargazer/plugins/capture/nfqueue/nfqueue.cpp +++ b/projects/stargazer/plugins/capture/nfqueue/nfqueue.cpp @@ -87,8 +87,7 @@ return "cap_nfqueue v.1.0"; } //----------------------------------------------------------------------------- NFQ_CAP::NFQ_CAP() - : nonstop(false), - isRunning(false), + : isRunning(false), queueNumber(0), nfqHandle(NULL), queueHandle(NULL), @@ -152,15 +151,7 @@ if (nfq_set_mode(queueHandle, NFQNL_COPY_PACKET, 0xffFF) < 0) return -1; } -nonstop = true; - -if (pthread_create(&thread, NULL, Run, this)) - { - errorStr = "Cannot create thread."; - logger("Cannot create thread."); - printfd(__FILE__, "Cannot create thread\n"); - return -1; - } +m_thread = std::jthread([this](auto token){ Run(std::move(token)); }); return 0; } @@ -170,7 +161,7 @@ int NFQ_CAP::Stop() if (!isRunning) return 0; -nonstop = false; +m_thread.request_stop(); //5 seconds to thread stops itself for (int i = 0; i < 25 && isRunning; i++) @@ -180,28 +171,9 @@ for (int i = 0; i < 25 && isRunning; i++) } //after 5 seconds waiting thread still running. now killing it if (isRunning) - { - if (pthread_kill(thread, SIGUSR1)) - { - errorStr = "Cannot kill thread."; - logger("Cannot send signal to thread."); - return -1; - } - for (int i = 0; i < 25 && isRunning; ++i) - { - struct timespec ts = {0, 200000000}; - nanosleep(&ts, NULL); - } - if (isRunning) - { - errorStr = "NFQ_CAP not stopped."; - logger("Cannot stop thread."); - printfd(__FILE__, "Cannot stop thread\n"); - return -1; - } - } - -pthread_join(thread, NULL); + m_thread.detach(); +else + m_thread.join(); nfq_destroy_queue(queueHandle); nfq_close(nfqHandle); @@ -209,19 +181,18 @@ nfq_close(nfqHandle); return 0; } //----------------------------------------------------------------------------- -void * NFQ_CAP::Run(void * d) +void NFQ_CAP::Run(std::stop_token token) { sigset_t signalSet; sigfillset(&signalSet); pthread_sigmask(SIG_BLOCK, &signalSet, NULL); -NFQ_CAP * dc = static_cast<NFQ_CAP *>(d); -dc->isRunning = true; +isRunning = true; -int fd = nfq_fd(dc->nfqHandle); +int fd = nfq_fd(nfqHandle); char buf[4096]; -while (dc->nonstop) +while (!token.stop_requested()) { if (!WaitPackets(fd)) continue; @@ -229,15 +200,14 @@ while (dc->nonstop) int rv = read(fd, buf, sizeof(buf)); if (rv < 0) { - dc->errorStr = std::string("Read error: ") + strerror(errno); - dc->logger(dc->errorStr); + errorStr = std::string("Read error: ") + strerror(errno); + logger(errorStr); break; } - nfq_handle_packet(dc->nfqHandle, buf, rv); + nfq_handle_packet(nfqHandle, buf, rv); } -dc->isRunning = false; -return NULL; +isRunning = false; } //----------------------------------------------------------------------------- void NFQ_CAP::Process(const STG::RawPacket & packet) diff --git a/projects/stargazer/plugins/capture/nfqueue/nfqueue.h b/projects/stargazer/plugins/capture/nfqueue/nfqueue.h index 7d71bcd2..402e36bf 100644 --- a/projects/stargazer/plugins/capture/nfqueue/nfqueue.h +++ b/projects/stargazer/plugins/capture/nfqueue/nfqueue.h @@ -26,8 +26,10 @@ #include <string> #include <vector> - -#include <pthread.h> +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#include <jthread.hpp> +#pragma GCC diagnostic pop namespace STG { @@ -69,12 +71,11 @@ private: NFQ_CAP(const NFQ_CAP & rvalue); NFQ_CAP & operator=(const NFQ_CAP & rvalue); - static void * Run(void *); + void Run(std::stop_token token); mutable std::string errorStr; - pthread_t thread; - bool nonstop; + std::jthread m_thread; bool isRunning; STG::ModuleSettings settings; diff --git a/projects/stargazer/plugins/capture/pcap/pcap_cap.cpp b/projects/stargazer/plugins/capture/pcap/pcap_cap.cpp index 394487f3..323bd7bf 100644 --- a/projects/stargazer/plugins/capture/pcap/pcap_cap.cpp +++ b/projects/stargazer/plugins/capture/pcap/pcap_cap.cpp @@ -61,8 +61,7 @@ return "pcap_cap v.1.0"; } //----------------------------------------------------------------------------- PCAP_CAP::PCAP_CAP() - : nonstop(false), - isRunning(false), + : isRunning(false), traffCnt(NULL), logger(STG::PluginLogger::get("pcap_cap")) { @@ -178,15 +177,7 @@ while (it != devices.end()) ++it; } -nonstop = true; - -if (pthread_create(&thread, NULL, Run, this)) - { - errorStr = "Cannot create thread."; - logger("Cannot create thread."); - printfd(__FILE__, "Cannot create thread\n"); - return -1; - } +m_thread = std::jthread([this](auto token){ Run(std::move(token)); }); return 0; } @@ -196,7 +187,7 @@ int PCAP_CAP::Stop() if (!isRunning) return 0; -nonstop = false; +m_thread.request_stop(); //5 seconds to thread stops itself for (int i = 0; i < 25 && isRunning; i++) @@ -206,28 +197,9 @@ for (int i = 0; i < 25 && isRunning; i++) } //after 5 seconds waiting thread still running. now killing it if (isRunning) - { - if (pthread_kill(thread, SIGUSR1)) - { - errorStr = "Cannot kill thread."; - logger("Cannot send signal to thread."); - return -1; - } - for (int i = 0; i < 25 && isRunning; ++i) - { - struct timespec ts = {0, 200000000}; - nanosleep(&ts, NULL); - } - if (isRunning) - { - errorStr = "PCAP_CAP not stopped."; - logger("Cannot stop thread."); - printfd(__FILE__, "Cannot stop thread\n"); - return -1; - } - } - -pthread_join(thread, NULL); + m_thread.detach(); +else + m_thread.join(); for (DEV_MAP::iterator it(devices.begin()); it != devices.end(); ++it) { @@ -238,35 +210,33 @@ for (DEV_MAP::iterator it(devices.begin()); it != devices.end(); ++it) return 0; } //----------------------------------------------------------------------------- -void * PCAP_CAP::Run(void * d) +void PCAP_CAP::Run(std::stop_token token) { sigset_t signalSet; sigfillset(&signalSet); pthread_sigmask(SIG_BLOCK, &signalSet, NULL); -PCAP_CAP * dc = static_cast<PCAP_CAP *>(d); -dc->isRunning = true; +isRunning = true; fd_set fds; FD_ZERO(&fds); int maxFd = 0; -for (DEV_MAP::const_iterator it(dc->devices.begin()); it != dc->devices.end(); ++it) +for (DEV_MAP::const_iterator it(devices.begin()); it != devices.end(); ++it) { FD_SET(it->fd, &fds); maxFd = std::max(maxFd, it->fd); } -while (dc->nonstop) +while (!token.stop_requested()) { fd_set rfds = fds; struct timeval tv = {0, 500000}; if (select(maxFd + 1, &rfds, NULL, NULL, &tv) > 0) - dc->TryRead(rfds); + TryRead(rfds); } -dc->isRunning = false; -return NULL; +isRunning = false; } void PCAP_CAP::TryRead(const fd_set & set) diff --git a/projects/stargazer/plugins/capture/pcap/pcap_cap.h b/projects/stargazer/plugins/capture/pcap/pcap_cap.h index f47c6b8d..e72c3e74 100644 --- a/projects/stargazer/plugins/capture/pcap/pcap_cap.h +++ b/projects/stargazer/plugins/capture/pcap/pcap_cap.h @@ -26,9 +26,12 @@ #include <string> #include <vector> +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#include <jthread.hpp> +#pragma GCC diagnostic pop #include <pcap.h> -#include <pthread.h> #include <sys/select.h> namespace STG @@ -45,7 +48,7 @@ struct Settings; struct DEV { DEV() : device("any"), filterExpression("ip"), handle(NULL), fd(-1) {} - DEV(const std::string & d) : device(d), filterExpression("ip"), handle(NULL), fd(-1) {} + explicit DEV(const std::string & d) : device(d), filterExpression("ip"), handle(NULL), fd(-1) {} DEV(const std::string & d, const std::string & f) : device(d), filterExpression(f), handle(NULL), fd(-1) {} @@ -84,12 +87,11 @@ private: void TryRead(const fd_set & set); void TryReadDev(const DEV & dev); - static void * Run(void *); + void Run(std::stop_token token); mutable std::string errorStr; - pthread_t thread; - bool nonstop; + std::jthread m_thread; bool isRunning; STG::ModuleSettings settings; DEV_MAP devices; diff --git a/projects/stargazer/plugins/configuration/sgconfig/stgconfig.cpp b/projects/stargazer/plugins/configuration/sgconfig/stgconfig.cpp index a63478bd..0896bb85 100644 --- a/projects/stargazer/plugins/configuration/sgconfig/stgconfig.cpp +++ b/projects/stargazer/plugins/configuration/sgconfig/stgconfig.cpp @@ -127,6 +127,8 @@ int STG_CONFIG::Stop() if (isRunning) m_thread.detach(); + else + m_thread.join(); return 0; } diff --git a/projects/stargazer/plugins/other/ping/ping.cpp b/projects/stargazer/plugins/other/ping/ping.cpp index a8dda2a6..53f7b2f0 100644 --- a/projects/stargazer/plugins/other/ping/ping.cpp +++ b/projects/stargazer/plugins/other/ping/ping.cpp @@ -128,6 +128,8 @@ while (users_iter != usersList.end()) if (isRunning) m_thread.detach(); +else + m_thread.join(); return 0; } diff --git a/projects/stargazer/plugins/other/rscript/rscript.cpp b/projects/stargazer/plugins/other/rscript/rscript.cpp index 8b0e2054..95699e10 100644 --- a/projects/stargazer/plugins/other/rscript/rscript.cpp +++ b/projects/stargazer/plugins/other/rscript/rscript.cpp @@ -265,6 +265,8 @@ if (isRunning) logger("Cannot stop thread."); m_thread.detach(); } +else + m_thread.join(); return 0; } diff --git a/projects/stargazer/plugins/other/smux/smux.cpp b/projects/stargazer/plugins/other/smux/smux.cpp index 77df9348..e0ddfffc 100644 --- a/projects/stargazer/plugins/other/smux/smux.cpp +++ b/projects/stargazer/plugins/other/smux/smux.cpp @@ -214,6 +214,8 @@ if (!stopped) if (!stopped) m_thread.detach(); +else + m_thread.join(); ResetNotifiers(); diff --git a/projects/stargazer/plugins/store/firebird/firebird_store.h b/projects/stargazer/plugins/store/firebird/firebird_store.h index 14f0b269..736451ec 100644 --- a/projects/stargazer/plugins/store/firebird/firebird_store.h +++ b/projects/stargazer/plugins/store/firebird/firebird_store.h @@ -30,10 +30,6 @@ #include <string> #include <vector> -struct ToLower { - char operator() (char c) const { return static_cast<char>(std::tolower(c)); } -}; - class FIREBIRD_STORE : public STG::Store { public: FIREBIRD_STORE(); diff --git a/projects/stargazer/plugins/store/postgresql/postgresql_store.cpp b/projects/stargazer/plugins/store/postgresql/postgresql_store.cpp index 2146d664..ba478966 100644 --- a/projects/stargazer/plugins/store/postgresql/postgresql_store.cpp +++ b/projects/stargazer/plugins/store/postgresql/postgresql_store.cpp @@ -40,9 +40,6 @@ #include "postgresql_store.h" -#include "postgresql_store_utils.h" -#include "postgresql_store.h" - #include "stg/common.h" // str2x, printfd #include <string> diff --git a/projects/stargazer/plugins/store/postgresql/postgresql_store_utils.h b/projects/stargazer/plugins/store/postgresql/postgresql_store_utils.h deleted file mode 100644 index 4ffa6ecf..00000000 --- a/projects/stargazer/plugins/store/postgresql/postgresql_store_utils.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef POSTGRESQL_UTILS_STORE_H -#define POSTGRESQL_UTILS_STORE_H - -#include <functional> - -struct ToLower : public std::unary_function<char, char> -{ -char operator() (char c) const { return static_cast<char>(std::tolower(c)); } -}; - -#endif diff --git a/projects/stargazer/traffcounter_impl.cpp b/projects/stargazer/traffcounter_impl.cpp index e61be966..9b0fd966 100644 --- a/projects/stargazer/traffcounter_impl.cpp +++ b/projects/stargazer/traffcounter_impl.cpp @@ -128,9 +128,7 @@ users->CloseSearch(h); //5 seconds to thread stops itself struct timespec ts = {0, 200000000}; for (int i = 0; i < 25 && !stopped; i++) - { nanosleep(&ts, NULL); - } if (!stopped) { @@ -138,6 +136,8 @@ if (!stopped) return -1; } +m_thread.join(); + printfd(__FILE__, "TraffCounter::Stop()\n"); return 0; diff --git a/projects/stargazer/traffcounter_impl.h b/projects/stargazer/traffcounter_impl.h index 42774bf9..ed639f5c 100644 --- a/projects/stargazer/traffcounter_impl.h +++ b/projects/stargazer/traffcounter_impl.h @@ -244,7 +244,7 @@ void TRF_IP_BEFORE::Notify(const uint32_t & oldValue, const uint32_t &) if (!oldValue) return; -EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TraffCounterImpl::DelUser, oldValue); +EVENT_LOOP::instance().Enqueue(traffCnt, &TraffCounterImpl::DelUser, oldValue); } //----------------------------------------------------------------------------- inline @@ -254,20 +254,20 @@ void TRF_IP_AFTER::Notify(const uint32_t &, const uint32_t & newValue) if (!newValue) return; -EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TraffCounterImpl::AddUser, user); +EVENT_LOOP::instance().Enqueue(traffCnt, &TraffCounterImpl::AddUser, user); } //----------------------------------------------------------------------------- inline void ADD_USER_NONIFIER::Notify(const UserImplPtr & user) { -EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TraffCounterImpl::SetUserNotifiers, user); +EVENT_LOOP::instance().Enqueue(traffCnt, &TraffCounterImpl::SetUserNotifiers, user); } //----------------------------------------------------------------------------- inline void DEL_USER_NONIFIER::Notify(const UserImplPtr & user) { -EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TraffCounterImpl::UnSetUserNotifiers, user); -EVENT_LOOP_SINGLETON::GetInstance().Enqueue(traffCnt, &TraffCounterImpl::DelUser, user->GetCurrIP()); +EVENT_LOOP::instance().Enqueue(traffCnt, &TraffCounterImpl::UnSetUserNotifiers, user); +EVENT_LOOP::instance().Enqueue(traffCnt, &TraffCounterImpl::DelUser, user->GetCurrIP()); } //----------------------------------------------------------------------------- } diff --git a/projects/stargazer/users_impl.cpp b/projects/stargazer/users_impl.cpp index 2e40f03e..ee25fb2c 100644 --- a/projects/stargazer/users_impl.cpp +++ b/projects/stargazer/users_impl.cpp @@ -534,6 +534,8 @@ if (isRunning) //TODO pthread_cancel() m_thread.detach(); } +else + m_thread.join(); printfd(__FILE__, "Before USERS::Run()\n"); for_each(users.begin(), users.end(), [](auto& user){ user.Run(); });