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