Add a new task pool class to LLDB
The purpose of the class is to make it easy to execute tasks in parallel Basic design goals: * Have a very lightweight and easy to use interface where a list of lambdas can be executed in parallel * Use a global thread pool to limit the number of threads used (std::async don't do it on Linux) and to eliminate the thread creation overhead * Destroy the thread currently not in use to avoid the confusion caused by them during debugging LLDB Possible future improvements: * Possibility to cancel already added, but not yet started tasks * Parallel for_each implementation * Optimizations in the thread creation destroyation code Differential revision: http://reviews.llvm.org/D13727 llvm-svn: 250820
This commit is contained in:
88
lldb/source/Utility/TaskPool.cpp
Normal file
88
lldb/source/Utility/TaskPool.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
//===--------------------- TaskPool.cpp -------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lldb/Utility/TaskPool.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
class TaskPoolImpl
|
||||
{
|
||||
public:
|
||||
static TaskPoolImpl&
|
||||
GetInstance();
|
||||
|
||||
void
|
||||
AddTask(std::function<void()>&& task_fn);
|
||||
|
||||
private:
|
||||
TaskPoolImpl();
|
||||
|
||||
static void
|
||||
Worker(TaskPoolImpl* pool);
|
||||
|
||||
std::queue<std::function<void()>> m_tasks;
|
||||
std::mutex m_tasks_mutex;
|
||||
uint32_t m_thread_count;
|
||||
};
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
||||
TaskPoolImpl&
|
||||
TaskPoolImpl::GetInstance()
|
||||
{
|
||||
static TaskPoolImpl g_task_pool_impl;
|
||||
return g_task_pool_impl;
|
||||
}
|
||||
|
||||
void
|
||||
TaskPool::AddTaskImpl(std::function<void()>&& task_fn)
|
||||
{
|
||||
TaskPoolImpl::GetInstance().AddTask(std::move(task_fn));
|
||||
}
|
||||
|
||||
TaskPoolImpl::TaskPoolImpl() :
|
||||
m_thread_count(0)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TaskPoolImpl::AddTask(std::function<void()>&& task_fn)
|
||||
{
|
||||
static const uint32_t max_threads = std::thread::hardware_concurrency();
|
||||
|
||||
std::unique_lock<std::mutex> lock(m_tasks_mutex);
|
||||
m_tasks.emplace(std::move(task_fn));
|
||||
if (m_thread_count < max_threads)
|
||||
{
|
||||
m_thread_count++;
|
||||
lock.unlock();
|
||||
|
||||
std::thread (Worker, this).detach();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TaskPoolImpl::Worker(TaskPoolImpl* pool)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(pool->m_tasks_mutex);
|
||||
if (pool->m_tasks.empty())
|
||||
{
|
||||
pool->m_thread_count--;
|
||||
break;
|
||||
}
|
||||
|
||||
std::function<void()> f = pool->m_tasks.front();
|
||||
pool->m_tasks.pop();
|
||||
lock.unlock();
|
||||
|
||||
f();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user