1 //===--------------------- TaskPool.h ---------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #ifndef utility_TaskPool_h_
11 #define utility_TaskPool_h_
13 #include "llvm/ADT/STLExtras.h"
19 #include <type_traits>
21 namespace lldb_private {
23 // Global TaskPool class for running tasks in parallel on a set of worker
24 // thread created the first time the task pool is used. The TaskPool provide no
25 // guarantee about the order the task will be run and about what tasks will run
26 // in parallel. None of the task added to the task pool should block on
27 // something (mutex, future, condition variable) what will be set only by the
28 // completion of an other task on the task pool as they may run on the same
29 // thread sequentally.
32 // Add a new task to the task pool and return a std::future belonging to the
33 // newly created task. The caller of this function has to wait on the future
34 // for this task to complete.
35 template <typename F, typename... Args>
36 static std::future<typename std::result_of<F(Args...)>::type>
37 AddTask(F &&f, Args &&... args);
39 // Run all of the specified tasks on the task pool and wait until all of them
40 // are finished before returning. This method is intended to be used for
41 // small number tasks where listing them as function arguments is acceptable.
42 // For running large number of tasks you should use AddTask for each task and
43 // then call wait() on each returned future.
44 template <typename... T> static void RunTasks(T &&... tasks);
49 template <typename... T> struct RunTaskImpl;
51 static void AddTaskImpl(std::function<void()> &&task_fn);
54 template <typename F, typename... Args>
55 std::future<typename std::result_of<F(Args...)>::type>
56 TaskPool::AddTask(F &&f, Args &&... args) {
57 auto task_sp = std::make_shared<
58 std::packaged_task<typename std::result_of<F(Args...)>::type()>>(
59 std::bind(std::forward<F>(f), std::forward<Args>(args)...));
61 AddTaskImpl([task_sp]() { (*task_sp)(); });
63 return task_sp->get_future();
66 template <typename... T> void TaskPool::RunTasks(T &&... tasks) {
67 RunTaskImpl<T...>::Run(std::forward<T>(tasks)...);
70 template <typename Head, typename... Tail>
71 struct TaskPool::RunTaskImpl<Head, Tail...> {
72 static void Run(Head &&h, Tail &&... t) {
73 auto f = AddTask(std::forward<Head>(h));
74 RunTaskImpl<Tail...>::Run(std::forward<Tail>(t)...);
79 template <> struct TaskPool::RunTaskImpl<> {
83 // Run 'func' on every value from begin .. end-1. Each worker will grab
84 // 'batch_size' numbers at a time to work on, so for very fast functions, batch
85 // should be large enough to avoid too much cache line contention.
86 void TaskMapOverInt(size_t begin, size_t end,
87 const llvm::function_ref<void(size_t)> &func);
89 unsigned GetHardwareConcurrencyHint();
91 } // namespace lldb_private
93 #endif // #ifndef utility_TaskPool_h_