diff --git a/icinga-app/icinga.cpp b/icinga-app/icinga.cpp index 6b4af761438..5674a9ff243 100644 --- a/icinga-app/icinga.cpp +++ b/icinga-app/icinga.cpp @@ -447,6 +447,12 @@ static int Main() Configuration::SetReadOnly(true); + if (!Configuration::ConcurrencyWasModified) { + Configuration::Concurrency = std::thread::hardware_concurrency(); + } + + Application::GetTP().Restart(); + /* Ensure that all defined constants work in the way we expect them. */ HandleLegacyDefines(); diff --git a/lib/base/configuration.cpp b/lib/base/configuration.cpp index d163937e2a7..31ae6048844 100644 --- a/lib/base/configuration.cpp +++ b/lib/base/configuration.cpp @@ -12,7 +12,8 @@ String Configuration::ApiBindHost; String Configuration::ApiBindPort{"5665"}; bool Configuration::AttachDebugger{false}; String Configuration::CacheDir; -int Configuration::Concurrency{static_cast(std::thread::hardware_concurrency())}; +int Configuration::Concurrency{1}; +bool Configuration::ConcurrencyWasModified{false}; String Configuration::ConfigDir; String Configuration::DataDir; String Configuration::EventEngine; @@ -101,6 +102,7 @@ int Configuration::GetConcurrency() const void Configuration::SetConcurrency(int val, bool suppress_events, const Value& cookie) { HandleUserWrite("Concurrency", &Configuration::Concurrency, val, m_ReadOnly); + Configuration::ConcurrencyWasModified = true; } String Configuration::GetConfigDir() const diff --git a/lib/base/configuration.hpp b/lib/base/configuration.hpp index 560906596cc..a5aed01e8ea 100644 --- a/lib/base/configuration.hpp +++ b/lib/base/configuration.hpp @@ -118,6 +118,7 @@ class Configuration : public ObjectImpl static bool AttachDebugger; static String CacheDir; static int Concurrency; + static bool ConcurrencyWasModified; static String ConfigDir; static String DataDir; static String EventEngine; diff --git a/lib/base/io-engine.cpp b/lib/base/io-engine.cpp index 5dd3ee59cf6..056d3b9bfca 100644 --- a/lib/base/io-engine.cpp +++ b/lib/base/io-engine.cpp @@ -1,5 +1,6 @@ /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */ +#include "base/configuration.hpp" #include "base/exception.hpp" #include "base/io-engine.hpp" #include "base/lazy-init.hpp" @@ -84,10 +85,10 @@ boost::asio::io_context& IoEngine::GetIoContext() return m_IoContext; } -IoEngine::IoEngine() : m_IoContext(), m_KeepAlive(boost::asio::make_work_guard(m_IoContext)), m_Threads(decltype(m_Threads)::size_type(std::thread::hardware_concurrency() * 2u)), m_AlreadyExpiredTimer(m_IoContext) +IoEngine::IoEngine() : m_IoContext(), m_KeepAlive(boost::asio::make_work_guard(m_IoContext)), m_Threads(decltype(m_Threads)::size_type(Configuration::Concurrency * 2u)), m_AlreadyExpiredTimer(m_IoContext) { m_AlreadyExpiredTimer.expires_at(boost::posix_time::neg_infin); - m_CpuBoundSemaphore.store(std::thread::hardware_concurrency() * 3u / 2u); + m_CpuBoundSemaphore.store(Configuration::Concurrency * 3u / 2u); for (auto& thread : m_Threads) { thread = std::thread(&IoEngine::RunEventLoop, this); diff --git a/lib/base/threadpool.cpp b/lib/base/threadpool.cpp index 26787ab52a7..dc76e7b15bd 100644 --- a/lib/base/threadpool.cpp +++ b/lib/base/threadpool.cpp @@ -5,8 +5,7 @@ using namespace icinga; -ThreadPool::ThreadPool(size_t threads) - : m_Threads(threads), m_Pending(0) +ThreadPool::ThreadPool() : m_Pending(0) { Start(); } @@ -21,10 +20,15 @@ void ThreadPool::Start() boost::unique_lock lock (m_Mutex); if (!m_Pool) { - m_Pool = decltype(m_Pool)(new boost::asio::thread_pool(m_Threads)); + InitializePool(); } } +void ThreadPool::InitializePool() +{ + m_Pool = decltype(m_Pool)(new boost::asio::thread_pool(Configuration::Concurrency * 2u)); +} + void ThreadPool::Stop() { boost::unique_lock lock (m_Mutex); @@ -34,3 +38,14 @@ void ThreadPool::Stop() m_Pool = nullptr; } } + +void ThreadPool::Restart() +{ + boost::unique_lock lock (m_Mutex); + + if (m_Pool) { + m_Pool->join(); + } + + InitializePool(); +} diff --git a/lib/base/threadpool.hpp b/lib/base/threadpool.hpp index af351cd7acb..d30fa694c9a 100644 --- a/lib/base/threadpool.hpp +++ b/lib/base/threadpool.hpp @@ -4,6 +4,7 @@ #define THREADPOOL_H #include "base/atomic.hpp" +#include "base/configuration.hpp" #include "base/exception.hpp" #include "base/logger.hpp" #include @@ -36,11 +37,12 @@ class ThreadPool public: typedef std::function WorkFunction; - ThreadPool(size_t threads = std::thread::hardware_concurrency() * 2u); + ThreadPool(); ~ThreadPool(); void Start(); void Stop(); + void Restart(); /** * Appends a work item to the work queue. Work items will be processed in FIFO order. @@ -89,8 +91,9 @@ class ThreadPool private: boost::shared_mutex m_Mutex; std::unique_ptr m_Pool; - size_t m_Threads; Atomic m_Pending; + + void InitializePool(); }; }