LLVM  4.0.0
ThreadPool.h
Go to the documentation of this file.
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/Support/thread.h"
18 
19 #ifdef _MSC_VER
20 // concrt.h depends on eh.h for __uncaught_exception declaration
21 // even if we disable exceptions.
22 #include <eh.h>
23 
24 // Disable warnings from ppltasks.h transitively included by <future>.
25 #pragma warning(push)
26 #pragma warning(disable:4530)
27 #pragma warning(disable:4062)
28 #endif
29 
30 #include <future>
31 
32 #ifdef _MSC_VER
33 #pragma warning(pop)
34 #endif
35 
36 #include <atomic>
37 #include <condition_variable>
38 #include <functional>
39 #include <memory>
40 #include <mutex>
41 #include <queue>
42 #include <utility>
43 
44 namespace llvm {
45 
46 /// A ThreadPool for asynchronous parallel execution on a defined number of
47 /// threads.
48 ///
49 /// The pool keeps a vector of threads alive, waiting on a condition variable
50 /// for some work to become available.
51 class ThreadPool {
52 public:
53 #ifndef _MSC_VER
54  using VoidTy = void;
55  using TaskTy = std::function<void()>;
56  using PackagedTaskTy = std::packaged_task<void()>;
57 #else
58  // MSVC 2013 has a bug and can't use std::packaged_task<void()>;
59  // We force it to use bool(bool) instead.
60  using VoidTy = bool;
61  using TaskTy = std::function<bool(bool)>;
62  using PackagedTaskTy = std::packaged_task<bool(bool)>;
63 #endif
64 
65  /// Construct a pool with the number of core available on the system (or
66  /// whatever the value returned by std::thread::hardware_concurrency() is).
67  ThreadPool();
68 
69  /// Construct a pool of \p ThreadCount threads
70  ThreadPool(unsigned ThreadCount);
71 
72  /// Blocking destructor: the pool will wait for all the threads to complete.
73  ~ThreadPool();
74 
75  /// Asynchronous submission of a task to the pool. The returned future can be
76  /// used to wait for the task to finish and is *non-blocking* on destruction.
77  template <typename Function, typename... Args>
78  inline std::shared_future<VoidTy> async(Function &&F, Args &&... ArgList) {
79  auto Task =
80  std::bind(std::forward<Function>(F), std::forward<Args>(ArgList)...);
81 #ifndef _MSC_VER
82  return asyncImpl(std::move(Task));
83 #else
84  // This lambda has to be marked mutable because MSVC 2013's std::bind call
85  // operator isn't const qualified.
86  return asyncImpl([Task](VoidTy) mutable -> VoidTy {
87  Task();
88  return VoidTy();
89  });
90 #endif
91  }
92 
93  /// Asynchronous submission of a task to the pool. The returned future can be
94  /// used to wait for the task to finish and is *non-blocking* on destruction.
95  template <typename Function>
96  inline std::shared_future<VoidTy> async(Function &&F) {
97 #ifndef _MSC_VER
98  return asyncImpl(std::forward<Function>(F));
99 #else
100  return asyncImpl([F] (VoidTy) -> VoidTy { F(); return VoidTy(); });
101 #endif
102  }
103 
104  /// Blocking wait for all the threads to complete and the queue to be empty.
105  /// It is an error to try to add new tasks while blocking on this call.
106  void wait();
107 
108 private:
109  /// Asynchronous submission of a task to the pool. The returned future can be
110  /// used to wait for the task to finish and is *non-blocking* on destruction.
111  std::shared_future<VoidTy> asyncImpl(TaskTy F);
112 
113  /// Threads in flight
114  std::vector<llvm::thread> Threads;
115 
116  /// Tasks waiting for execution in the pool.
117  std::queue<PackagedTaskTy> Tasks;
118 
119  /// Locking and signaling for accessing the Tasks queue.
120  std::mutex QueueLock;
121  std::condition_variable QueueCondition;
122 
123  /// Locking and signaling for job completion
124  std::mutex CompletionLock;
125  std::condition_variable CompletionCondition;
126 
127  /// Keep track of the number of thread actually busy
128  std::atomic<unsigned> ActiveThreads;
129 
130 #if LLVM_ENABLE_THREADS // avoids warning for unused variable
131  /// Signal for the destruction of the pool, asking thread to exit.
132  bool EnableFlag;
133 #endif
134 };
135 }
136 
137 #endif // LLVM_SUPPORT_THREAD_POOL_H
std::packaged_task< void()> PackagedTaskTy
Definition: ThreadPool.h:56
std::function< void()> TaskTy
Definition: ThreadPool.h:55
std::shared_future< VoidTy > async(Function &&F)
Asynchronous submission of a task to the pool.
Definition: ThreadPool.h:96
~ThreadPool()
Blocking destructor: the pool will wait for all the threads to complete.
Definition: ThreadPool.cpp:103
#define F(x, y, z)
Definition: MD5.cpp:51
A ThreadPool for asynchronous parallel execution on a defined number of threads.
Definition: ThreadPool.h:51
std::shared_future< VoidTy > async(Function &&F, Args &&...ArgList)
Asynchronous submission of a task to the pool.
Definition: ThreadPool.h:78
ThreadPool()
Construct a pool with the number of core available on the system (or whatever the value returned by s...
Definition: ThreadPool.cpp:24
void wait()
Blocking wait for all the threads to complete and the queue to be empty.
Definition: ThreadPool.cpp:75