Line data Source code
1 : //===-- llvm/Support/ThreadPool.h - A ThreadPool implementation -*- 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 : // This file defines a crude C++11 based thread pool.
11 : //
12 : //===----------------------------------------------------------------------===//
13 :
14 : #ifndef LLVM_SUPPORT_THREAD_POOL_H
15 : #define LLVM_SUPPORT_THREAD_POOL_H
16 :
17 : #include "llvm/Config/llvm-config.h"
18 : #include "llvm/Support/thread.h"
19 :
20 : #include <future>
21 :
22 : #include <atomic>
23 : #include <condition_variable>
24 : #include <functional>
25 : #include <memory>
26 : #include <mutex>
27 : #include <queue>
28 : #include <utility>
29 :
30 : namespace llvm {
31 :
32 : /// A ThreadPool for asynchronous parallel execution on a defined number of
33 : /// threads.
34 : ///
35 : /// The pool keeps a vector of threads alive, waiting on a condition variable
36 : /// for some work to become available.
37 : class ThreadPool {
38 : public:
39 : using TaskTy = std::function<void()>;
40 : using PackagedTaskTy = std::packaged_task<void()>;
41 :
42 : /// Construct a pool with the number of threads found by
43 : /// hardware_concurrency().
44 : ThreadPool();
45 :
46 : /// Construct a pool of \p ThreadCount threads
47 : ThreadPool(unsigned ThreadCount);
48 :
49 : /// Blocking destructor: the pool will wait for all the threads to complete.
50 : ~ThreadPool();
51 :
52 : /// Asynchronous submission of a task to the pool. The returned future can be
53 : /// used to wait for the task to finish and is *non-blocking* on destruction.
54 : template <typename Function, typename... Args>
55 516 : inline std::shared_future<void> async(Function &&F, Args &&... ArgList) {
56 154 : auto Task =
57 : std::bind(std::forward<Function>(F), std::forward<Args>(ArgList)...);
58 758 : return asyncImpl(std::move(Task));
59 : }
60 :
61 : /// Asynchronous submission of a task to the pool. The returned future can be
62 : /// used to wait for the task to finish and is *non-blocking* on destruction.
63 : template <typename Function>
64 203 : inline std::shared_future<void> async(Function &&F) {
65 213 : return asyncImpl(std::forward<Function>(F));
66 : }
67 :
68 : /// Blocking wait for all the threads to complete and the queue to be empty.
69 : /// It is an error to try to add new tasks while blocking on this call.
70 : void wait();
71 :
72 : private:
73 : /// Asynchronous submission of a task to the pool. The returned future can be
74 : /// used to wait for the task to finish and is *non-blocking* on destruction.
75 : std::shared_future<void> asyncImpl(TaskTy F);
76 :
77 : /// Threads in flight
78 : std::vector<llvm::thread> Threads;
79 :
80 : /// Tasks waiting for execution in the pool.
81 : std::queue<PackagedTaskTy> Tasks;
82 :
83 : /// Locking and signaling for accessing the Tasks queue.
84 : std::mutex QueueLock;
85 : std::condition_variable QueueCondition;
86 :
87 : /// Locking and signaling for job completion
88 : std::mutex CompletionLock;
89 : std::condition_variable CompletionCondition;
90 :
91 : /// Keep track of the number of thread actually busy
92 : std::atomic<unsigned> ActiveThreads;
93 :
94 : #if LLVM_ENABLE_THREADS // avoids warning for unused variable
95 : /// Signal for the destruction of the pool, asking thread to exit.
96 : bool EnableFlag;
97 : #endif
98 : };
99 : }
100 :
101 : #endif // LLVM_SUPPORT_THREAD_POOL_H
|