blob: f66f7bf9170d862d2dc1e32e110b2990b298011c [file] [log] [blame]
Tamas Berghammerccb36762015-10-20 12:42:05 +00001//===--------------------- TaskPool.cpp -------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Utility/TaskPool.h"
11
Kate Stoneb9c1b512016-09-06 20:57:50 +000012namespace {
13class TaskPoolImpl {
14public:
15 static TaskPoolImpl &GetInstance();
Tamas Berghammerccb36762015-10-20 12:42:05 +000016
Kate Stoneb9c1b512016-09-06 20:57:50 +000017 void AddTask(std::function<void()> &&task_fn);
Tamas Berghammerccb36762015-10-20 12:42:05 +000018
Kate Stoneb9c1b512016-09-06 20:57:50 +000019private:
20 TaskPoolImpl();
Tamas Berghammerccb36762015-10-20 12:42:05 +000021
Kate Stoneb9c1b512016-09-06 20:57:50 +000022 static void Worker(TaskPoolImpl *pool);
Tamas Berghammerccb36762015-10-20 12:42:05 +000023
Kate Stoneb9c1b512016-09-06 20:57:50 +000024 std::queue<std::function<void()>> m_tasks;
25 std::mutex m_tasks_mutex;
26 uint32_t m_thread_count;
27};
Tamas Berghammerccb36762015-10-20 12:42:05 +000028
29} // end of anonymous namespace
30
Kate Stoneb9c1b512016-09-06 20:57:50 +000031TaskPoolImpl &TaskPoolImpl::GetInstance() {
32 static TaskPoolImpl g_task_pool_impl;
33 return g_task_pool_impl;
Tamas Berghammerccb36762015-10-20 12:42:05 +000034}
35
Kate Stoneb9c1b512016-09-06 20:57:50 +000036void TaskPool::AddTaskImpl(std::function<void()> &&task_fn) {
37 TaskPoolImpl::GetInstance().AddTask(std::move(task_fn));
Tamas Berghammerccb36762015-10-20 12:42:05 +000038}
39
Kate Stoneb9c1b512016-09-06 20:57:50 +000040TaskPoolImpl::TaskPoolImpl() : m_thread_count(0) {}
41
42void TaskPoolImpl::AddTask(std::function<void()> &&task_fn) {
43 static const uint32_t max_threads = std::thread::hardware_concurrency();
44
45 std::unique_lock<std::mutex> lock(m_tasks_mutex);
46 m_tasks.emplace(std::move(task_fn));
47 if (m_thread_count < max_threads) {
48 m_thread_count++;
49 // Note that this detach call needs to happen with the m_tasks_mutex held.
50 // This prevents the thread
51 // from exiting prematurely and triggering a linux libc bug
52 // (https://sourceware.org/bugzilla/show_bug.cgi?id=19951).
53 std::thread(Worker, this).detach();
54 }
Tamas Berghammerccb36762015-10-20 12:42:05 +000055}
56
Kate Stoneb9c1b512016-09-06 20:57:50 +000057void TaskPoolImpl::Worker(TaskPoolImpl *pool) {
58 while (true) {
59 std::unique_lock<std::mutex> lock(pool->m_tasks_mutex);
60 if (pool->m_tasks.empty()) {
61 pool->m_thread_count--;
62 break;
Tamas Berghammerccb36762015-10-20 12:42:05 +000063 }
Tamas Berghammerccb36762015-10-20 12:42:05 +000064
Kate Stoneb9c1b512016-09-06 20:57:50 +000065 std::function<void()> f = pool->m_tasks.front();
66 pool->m_tasks.pop();
67 lock.unlock();
Tamas Berghammerccb36762015-10-20 12:42:05 +000068
Kate Stoneb9c1b512016-09-06 20:57:50 +000069 f();
70 }
Tamas Berghammerccb36762015-10-20 12:42:05 +000071}