feat-debug(thread_pool): log the job and which thread execute it for debugging purposes in case the thread never exit. also log in case a job is scheduled but none of the thread are currently available (#1190)
This commit is contained in:
parent
e1ce85fd71
commit
626394eca7
@ -22,6 +22,8 @@ namespace big
|
|||||||
LOG(VERBOSE) << "Allocating " << thread_count << " threads in thread pool.";
|
LOG(VERBOSE) << "Allocating " << thread_count << " threads in thread pool.";
|
||||||
this->m_thread_pool.reserve(thread_count);
|
this->m_thread_pool.reserve(thread_count);
|
||||||
|
|
||||||
|
m_available_thread_count = thread_count;
|
||||||
|
|
||||||
for (std::uint32_t i = 0; i < thread_count; i++)
|
for (std::uint32_t i = 0; i < thread_count; i++)
|
||||||
this->m_thread_pool.emplace_back(std::thread(&thread_pool::run, this));
|
this->m_thread_pool.emplace_back(std::thread(&thread_pool::run, this));
|
||||||
}
|
}
|
||||||
@ -41,13 +43,18 @@ namespace big
|
|||||||
m_thread_pool.clear();
|
m_thread_pool.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void thread_pool::push(std::function<void()> func)
|
void thread_pool::push(std::function<void()> func, std::source_location location)
|
||||||
{
|
{
|
||||||
if (func)
|
if (func)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
std::unique_lock lock(this->m_lock);
|
std::unique_lock lock(this->m_lock);
|
||||||
this->m_job_stack.push(std::move(func));
|
this->m_job_stack.push({func, location});
|
||||||
|
|
||||||
|
if (m_available_thread_count < m_job_stack.size())
|
||||||
|
{
|
||||||
|
LOG(WARNING) << "thread_pool potentially starved";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this->m_data_condition.notify_all();
|
this->m_data_condition.notify_all();
|
||||||
}
|
}
|
||||||
@ -68,18 +75,26 @@ namespace big
|
|||||||
if (this->m_job_stack.empty())
|
if (this->m_job_stack.empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
std::function<void()> job = std::move(this->m_job_stack.top());
|
thread_pool_job job = this->m_job_stack.top();
|
||||||
this->m_job_stack.pop();
|
this->m_job_stack.pop();
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
|
|
||||||
|
m_available_thread_count--;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
std::invoke(std::move(job));
|
const auto source_file = std::filesystem::path(job.m_source_location.file_name()).filename().string();
|
||||||
|
LOG(VERBOSE) << "Thread " << std::this_thread::get_id() << " executing " << source_file << ":"
|
||||||
|
<< job.m_source_location.line();
|
||||||
|
|
||||||
|
std::invoke(job.m_func);
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
LOG(WARNING) << "Exception thrown while executing job in thread:" << std::endl << e.what();
|
LOG(WARNING) << "Exception thrown while executing job in thread:" << std::endl << e.what();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_available_thread_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(VERBOSE) << "Thread " << std::this_thread::get_id() << " exiting...";
|
LOG(VERBOSE) << "Thread " << std::this_thread::get_id() << " exiting...";
|
||||||
|
@ -2,23 +2,31 @@
|
|||||||
|
|
||||||
namespace big
|
namespace big
|
||||||
{
|
{
|
||||||
|
struct thread_pool_job
|
||||||
|
{
|
||||||
|
std::function<void()> m_func;
|
||||||
|
std::source_location m_source_location;
|
||||||
|
};
|
||||||
|
|
||||||
class thread_pool
|
class thread_pool
|
||||||
{
|
{
|
||||||
std::atomic<bool> m_accept_jobs;
|
std::atomic<bool> m_accept_jobs;
|
||||||
std::condition_variable m_data_condition;
|
std::condition_variable m_data_condition;
|
||||||
|
|
||||||
std::stack<std::function<void()>> m_job_stack;
|
std::stack<thread_pool_job> m_job_stack;
|
||||||
std::mutex m_lock;
|
std::mutex m_lock;
|
||||||
std::vector<std::thread> m_thread_pool;
|
std::vector<std::thread> m_thread_pool;
|
||||||
|
|
||||||
std::thread m_managing_thread;
|
std::thread m_managing_thread;
|
||||||
|
|
||||||
|
std::atomic<size_t> m_available_thread_count;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
thread_pool();
|
thread_pool();
|
||||||
~thread_pool();
|
~thread_pool();
|
||||||
|
|
||||||
void destroy();
|
void destroy();
|
||||||
void push(std::function<void()> func);
|
void push(std::function<void()> func, std::source_location location = std::source_location::current());
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void create();
|
void create();
|
||||||
|
Reference in New Issue
Block a user