| 32 | /// blocking queue by Offer(). Each item is processed by a single user-supplied method. |
| 33 | template <typename T> |
| 34 | class ThreadPool : public CacheLineAligned { |
| 35 | public: |
| 36 | /// Signature of a work-processing function. Takes the integer id of the thread which is |
| 37 | /// calling it (ids run from 0 to num_threads - 1) and a reference to the item to |
| 38 | /// process. |
| 39 | typedef boost::function<void (int thread_id, const T& workitem)> WorkFunction; |
| 40 | |
| 41 | /// Creates a new thread pool without starting any threads. Code must call |
| 42 | /// Init() on this thread pool before any calls to Offer(). |
| 43 | /// -- num_threads: how many threads are part of this pool |
| 44 | /// -- queue_size: the maximum size of the queue on which work items are offered. If the |
| 45 | /// queue exceeds this size, subsequent calls to Offer will block until there is |
| 46 | /// capacity available. |
| 47 | /// -- work_function: the function to run every time an item is consumed from the queue |
| 48 | /// -- fault_injection_eligible - If set to true, allow fault injection at this |
| 49 | /// callsite (see thread_creation_fault_injection). If set to false, fault |
| 50 | /// injection is diabled at this callsite. Thread creation sites that crash |
| 51 | /// Impala or abort startup must have this set to false. |
| 52 | ThreadPool(const std::string& group, const std::string& thread_prefix, |
| 53 | uint32_t num_threads, uint32_t queue_size, const WorkFunction& work_function, |
| 54 | bool fault_injection_eligible = false) |
| 55 | : group_(group), thread_prefix_(thread_prefix), num_threads_(num_threads), |
| 56 | work_function_(work_function), work_queue_(queue_size), |
| 57 | fault_injection_eligible_(fault_injection_eligible) {} |
| 58 | |
| 59 | /// Destructor ensures that all threads are terminated before this object is freed |
| 60 | /// (otherwise they may continue to run and reference member variables) |
| 61 | virtual ~ThreadPool() { |
| 62 | Shutdown(); |
| 63 | Join(); |
| 64 | } |
| 65 | |
| 66 | /// Create the threads needed for this ThreadPool. Returns an error on any |
| 67 | /// error spawning the threads. |
| 68 | Status Init() { |
| 69 | for (int i = 0; i < num_threads_; ++i) { |
| 70 | std::stringstream threadname; |
| 71 | threadname << thread_prefix_ << "(" << i + 1 << ":" << num_threads_ << ")"; |
| 72 | std::unique_ptr<Thread> t; |
| 73 | Status status = Thread::Create(group_, threadname.str(), |
| 74 | boost::bind<void>(boost::mem_fn(&ThreadPool<T>::WorkerThread), this, i), &t, |
| 75 | fault_injection_eligible_); |
| 76 | if (!status.ok()) { |
| 77 | // The thread pool initialization failed. Shutdown any threads that were |
| 78 | // spawned. Note: Shutdown() and Join() are safe to call multiple times. |
| 79 | Shutdown(); |
| 80 | Join(); |
| 81 | return status; |
| 82 | } |
| 83 | threads_.AddThread(std::move(t)); |
| 84 | } |
| 85 | initialized_ = true; |
| 86 | return Status::OK(); |
| 87 | } |
| 88 | |
| 89 | /// Blocking operation that puts a work item on the queue. If the queue is full, blocks |
| 90 | /// until there is capacity available. The ThreadPool must be initialized before |
| 91 | /// calling this method. |
no outgoing calls