diff options
author | Tamas Berghammer <tberghammer@google.com> | 2015-10-20 12:42:05 +0000 |
---|---|---|
committer | Tamas Berghammer <tberghammer@google.com> | 2015-10-20 12:42:05 +0000 |
commit | ccb367609bdc19bccd73a8b7c79ee451096e738b (patch) | |
tree | 518068cbd9d2d22511f86b3b0daa4ae08492ec95 /lldb/source/Utility/TaskPool.cpp | |
parent | 21296d230ac53d16cab8daf5395afdd803f4f277 (diff) | |
download | llvm-ccb367609bdc19bccd73a8b7c79ee451096e738b.zip llvm-ccb367609bdc19bccd73a8b7c79ee451096e738b.tar.gz llvm-ccb367609bdc19bccd73a8b7c79ee451096e738b.tar.bz2 |
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
Diffstat (limited to 'lldb/source/Utility/TaskPool.cpp')
-rw-r--r-- | lldb/source/Utility/TaskPool.cpp | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/lldb/source/Utility/TaskPool.cpp b/lldb/source/Utility/TaskPool.cpp new file mode 100644 index 0000000..75fe59d --- /dev/null +++ b/lldb/source/Utility/TaskPool.cpp @@ -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(); + } +} |