Add a C++11 ThreadPool implementation in LLVM
[oota-llvm.git] / include / llvm / Support / ThreadPool.h
index c388c074c15035de5eacb5ef549502c0f4e8258b..8a90c85865a420a76cad23664e68335c3a26b2e2 100644 (file)
@@ -33,7 +33,15 @@ namespace llvm {
 /// 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).
@@ -48,17 +56,25 @@ public:
   /// 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.
@@ -68,13 +84,13 @@ public:
 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;
@@ -87,8 +103,10 @@ private:
   /// 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
 };
 }