/// for some work to become available.
class ThreadPool {
public:
- using TaskTy = std::function<void()>;
+#ifndef _MSC_VER
+ using VoidTy = void;
+#else
+ // MSVC 2013 has a bug and can't use std::packaged_task<void()>;
+ // We force it to use bool(bool) instead.
+ using VoidTy = bool;
+#endif
+ using TaskTy = std::function<VoidTy(VoidTy)>;
+ using PackagedTaskTy = std::packaged_task<VoidTy(VoidTy)>;
/// Construct a pool with the number of core available on the system (or
/// whatever the value returned by std::thread::hardware_concurrency() is).
/// Asynchronous submission of a task to the pool. The returned future can be
/// used to wait for the task to finish and is *non-blocking* on destruction.
template <typename Function, typename... Args>
- inline std::shared_future<void> async(Function &&F, Args &&... ArgList) {
+ inline std::shared_future<VoidTy> async(Function &&F, Args &&... ArgList) {
auto Task =
std::bind(std::forward<Function>(F), std::forward<Args...>(ArgList...));
- return asyncImpl(Task);
+#ifndef _MSC_VER
+ return asyncImpl(std::move(Task));
+#else
+ return asyncImpl([Task] (VoidTy) -> VoidTy { Task(); return VoidTy(); });
+#endif
}
/// Asynchronous submission of a task to the pool. The returned future can be
/// used to wait for the task to finish and is *non-blocking* on destruction.
template <typename Function>
- inline std::shared_future<void> async(Function &&F) {
- return asyncImpl(F);
+ inline std::shared_future<VoidTy> async(Function &&F) {
+#ifndef _MSC_VER
+ return asyncImpl(std::forward<Function>(F));
+#else
+ return asyncImpl([F] (VoidTy) -> VoidTy { F(); return VoidTy(); });
+#endif
}
/// Blocking wait for all the threads to complete and the queue to be empty.
private:
/// Asynchronous submission of a task to the pool. The returned future can be
/// used to wait for the task to finish and is *non-blocking* on destruction.
- std::shared_future<void> asyncImpl(TaskTy f);
+ std::shared_future<VoidTy> asyncImpl(TaskTy F);
/// Threads in flight
std::vector<llvm::thread> Threads;
/// Tasks waiting for execution in the pool.
- std::queue<std::packaged_task<void()>> Tasks;
+ std::queue<PackagedTaskTy> Tasks;
/// Locking and signaling for accessing the Tasks queue.
std::mutex QueueLock;
/// Keep track of the number of thread actually busy
std::atomic<unsigned> ActiveThreads;
+#if LLVM_ENABLE_THREADS // avoids warning for unused variable
/// Signal for the destruction of the pool, asking thread to exit.
bool EnableFlag;
+#endif
};
}