]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/include/lldb/Host/TaskPool.h
MFV r336851:
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / include / lldb / Host / TaskPool.h
1 //===--------------------- TaskPool.h ---------------------------*- 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 #ifndef utility_TaskPool_h_
11 #define utility_TaskPool_h_
12
13 #include "llvm/ADT/STLExtras.h"
14 #include <functional> // for bind, function
15 #include <future>
16 #include <list>
17 #include <memory>      // for make_shared
18 #include <mutex>       // for mutex, unique_lock, condition_variable
19 #include <type_traits> // for forward, result_of, move
20
21 namespace lldb_private {
22
23 // Global TaskPool class for running tasks in parallel on a set of worker thread
24 // created the first
25 // time the task pool is used. The TaskPool provide no guarantee about the order
26 // the task will be run
27 // and about what tasks will run in parallel. None of the task added to the task
28 // pool should block
29 // on something (mutex, future, condition variable) what will be set only by the
30 // completion of an
31 // other task on the task pool as they may run on the same thread sequentally.
32 class TaskPool {
33 public:
34   // Add a new task to the task pool and return a std::future belonging to the
35   // newly created task.
36   // The caller of this function has to wait on the future for this task to
37   // complete.
38   template <typename F, typename... Args>
39   static std::future<typename std::result_of<F(Args...)>::type>
40   AddTask(F &&f, Args &&... args);
41
42   // Run all of the specified tasks on the task pool and wait until all of them
43   // are finished
44   // before returning. This method is intended to be used for small number tasks
45   // where listing
46   // them as function arguments is acceptable. For running large number of tasks
47   // you should use
48   // AddTask for each task and then call wait() on each returned future.
49   template <typename... T> static void RunTasks(T &&... tasks);
50
51 private:
52   TaskPool() = delete;
53
54   template <typename... T> struct RunTaskImpl;
55
56   static void AddTaskImpl(std::function<void()> &&task_fn);
57 };
58
59 template <typename F, typename... Args>
60 std::future<typename std::result_of<F(Args...)>::type>
61 TaskPool::AddTask(F &&f, Args &&... args) {
62   auto task_sp = std::make_shared<
63       std::packaged_task<typename std::result_of<F(Args...)>::type()>>(
64       std::bind(std::forward<F>(f), std::forward<Args>(args)...));
65
66   AddTaskImpl([task_sp]() { (*task_sp)(); });
67
68   return task_sp->get_future();
69 }
70
71 template <typename... T> void TaskPool::RunTasks(T &&... tasks) {
72   RunTaskImpl<T...>::Run(std::forward<T>(tasks)...);
73 }
74
75 template <typename Head, typename... Tail>
76 struct TaskPool::RunTaskImpl<Head, Tail...> {
77   static void Run(Head &&h, Tail &&... t) {
78     auto f = AddTask(std::forward<Head>(h));
79     RunTaskImpl<Tail...>::Run(std::forward<Tail>(t)...);
80     f.wait();
81   }
82 };
83
84 template <> struct TaskPool::RunTaskImpl<> {
85   static void Run() {}
86 };
87
88 // Run 'func' on every value from begin .. end-1.  Each worker will grab
89 // 'batch_size' numbers at a time to work on, so for very fast functions, batch
90 // should be large enough to avoid too much cache line contention.
91 void TaskMapOverInt(size_t begin, size_t end,
92                     const llvm::function_ref<void(size_t)> &func);
93
94 unsigned GetHardwareConcurrencyHint();
95
96 } // namespace lldb_private
97
98 #endif // #ifndef utility_TaskPool_h_