thread_pool.h revision 1d54e73444e017d3a65234e0f193846f3e27472b
10e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier/* 20e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier * Copyright (C) 2012 The Android Open Source Project 30e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier * 40e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier * Licensed under the Apache License, Version 2.0 (the "License"); 50e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier * you may not use this file except in compliance with the License. 60e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier * You may obtain a copy of the License at 70e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier * 80e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier * http://www.apache.org/licenses/LICENSE-2.0 90e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier * 100e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier * Unless required by applicable law or agreed to in writing, software 110e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier * distributed under the License is distributed on an "AS IS" BASIS, 120e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier * See the License for the specific language governing permissions and 140e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier * limitations under the License. 150e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier */ 160e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier 170e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier#ifndef ART_SRC_THREAD_POOL_H_ 180e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier#define ART_SRC_THREAD_POOL_H_ 190e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier 200e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier#include <deque> 210e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier#include <vector> 220e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier 2335883cc623fdf475a4ead1dafcba9e9becc1ed11Mathieu Chartier#include "barrier.h" 2476b6167407c2b6f5d40ad895b2793a6b037f54b2Elliott Hughes#include "base/mutex.h" 2502b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier#include "closure.h" 260e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier#include "locks.h" 270e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier 280e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartiernamespace art { 290e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier 300e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartierclass ThreadPool; 310e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier 3202b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartierclass Task : public Closure { 3302b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartierpublic: 3402b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier // Called when references reaches 0. 3502b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier virtual void Finalize() { } 3602b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier}; 3702b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier 380e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartierclass ThreadPoolWorker { 390e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier public: 400e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier static const size_t kDefaultStackSize = 1 * MB; 410e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier 420e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier size_t GetStackSize() const { 430e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier return stack_size_; 440e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier } 450e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier 460e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier virtual ~ThreadPoolWorker(); 470e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier 4802b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier protected: 490e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier ThreadPoolWorker(ThreadPool* thread_pool, const std::string& name, size_t stack_size); 500e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier static void* Callback(void* arg) LOCKS_EXCLUDED(Locks::mutator_lock_); 5102b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier virtual void Run(); 520e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier 53d914eb2a839f7b40156ff0299a60e5cb80080b73Ian Rogers ThreadPool* const thread_pool_; 540e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier const std::string name_; 550e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier const size_t stack_size_; 560e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier pthread_t pthread_; 570e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier 580e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier friend class ThreadPool; 590e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier DISALLOW_COPY_AND_ASSIGN(ThreadPoolWorker); 600e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier}; 610e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier 620e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartierclass ThreadPool { 630e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier public: 640e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier // Returns the number of threads in the thread pool. 650e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier size_t GetThreadCount() const { 660e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier return threads_.size(); 670e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier } 680e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier 690e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier // Broadcast to the workers and tell them to empty out the work queue. 700e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier void StartWorkers(Thread* self); 710e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier 720e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier // Do not allow workers to grab any new tasks. 730e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier void StopWorkers(Thread* self); 740e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier 750e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier // Add a new task, the first available started worker will process it. Does not delete the task 760e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier // after running it, it is the caller's responsibility. 7702b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier void AddTask(Thread* self, Task* task); 780e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier 790e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier ThreadPool(size_t num_threads); 800e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier virtual ~ThreadPool(); 810e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier 820e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier // Wait for all tasks currently on queue to get completed. 831d54e73444e017d3a65234e0f193846f3e27472bIan Rogers void Wait(Thread* self, bool do_work, bool may_hold_locks); 840e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier 8502b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier size_t GetTaskCount(Thread* self); 860e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier 8702b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier // Returns the total amount of workers waited for tasks. 8802b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier uint64_t GetWaitTime() const { 8902b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier return total_wait_time_; 9002b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier } 9102b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier 9202b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier protected: 930e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier // Get a task to run, blocks if there are no tasks left 9402b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier virtual Task* GetTask(Thread* self); 9502b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier 9602b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier // Try to get a task, returning NULL if there is none available. 9702b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier Task* TryGetTask(Thread* self); 9802b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier Task* TryGetTaskLocked(Thread* self) EXCLUSIVE_LOCKS_REQUIRED(task_queue_lock_); 9902b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier 10002b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier // Are we shutting down? 10102b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier bool IsShuttingDown() const EXCLUSIVE_LOCKS_REQUIRED(task_queue_lock_) { 10202b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier return shutting_down_; 10302b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier } 1040e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier 1050e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier Mutex task_queue_lock_; 1060e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier ConditionVariable task_queue_condition_ GUARDED_BY(task_queue_lock_); 1070e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier ConditionVariable completion_condition_ GUARDED_BY(task_queue_lock_); 1080e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier volatile bool started_ GUARDED_BY(task_queue_lock_); 1090e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier volatile bool shutting_down_ GUARDED_BY(task_queue_lock_); 1100e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier // How many worker threads are waiting on the condition. 1110e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier volatile size_t waiting_count_ GUARDED_BY(task_queue_lock_); 11202b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier std::deque<Task*> tasks_ GUARDED_BY(task_queue_lock_); 1130e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier // TODO: make this immutable/const? 1140e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier std::vector<ThreadPoolWorker*> threads_; 11502b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier // Work balance detection. 11602b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier uint64_t start_time_ GUARDED_BY(task_queue_lock_); 11702b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier uint64_t total_wait_time_; 11835883cc623fdf475a4ead1dafcba9e9becc1ed11Mathieu Chartier Barrier creation_barier_; 1190e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier 1200e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier friend class ThreadPoolWorker; 12102b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier friend class WorkStealingWorker; 1220e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier DISALLOW_COPY_AND_ASSIGN(ThreadPool); 1230e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier}; 1240e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier 12502b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartierclass WorkStealingTask : public Task { 12602b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier public: 12702b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier WorkStealingTask() : ref_count_(0) { 12802b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier 12902b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier } 13002b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier 13102b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier size_t GetRefCount() const { 13202b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier return ref_count_; 13302b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier } 13402b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier 13502b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier virtual void StealFrom(Thread* self, WorkStealingTask* source) = 0; 13602b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier 13702b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier private: 13802b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier // How many people are referencing this task. 13902b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier size_t ref_count_; 14002b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier 14102b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier friend class WorkStealingWorker; 14202b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier}; 14302b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier 14402b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartierclass WorkStealingWorker : public ThreadPoolWorker { 14502b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier public: 14602b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier virtual ~WorkStealingWorker(); 14702b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier 14802b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier bool IsRunningTask() const { 14902b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier return task_ != NULL; 15002b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier } 15102b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier 15202b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier protected: 15302b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier WorkStealingTask* task_; 15402b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier 15502b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier WorkStealingWorker(ThreadPool* thread_pool, const std::string& name, size_t stack_size); 15602b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier virtual void Run(); 15702b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier 15802b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier friend class WorkStealingThreadPool; 15902b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier DISALLOW_COPY_AND_ASSIGN(WorkStealingWorker); 16002b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier}; 16102b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier 16202b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartierclass WorkStealingThreadPool : public ThreadPool { 16302b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier public: 16402b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier WorkStealingThreadPool(size_t num_threads); 16502b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier virtual ~WorkStealingThreadPool(); 16602b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier 16702b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier private: 16802b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier Mutex work_steal_lock_; 16902b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier // Which thread we are stealing from (round robin). 17002b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier size_t steal_index_; 17102b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier 17202b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier // Find a task to steal from 17302b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier WorkStealingTask* FindTaskToStealFrom(Thread* self) EXCLUSIVE_LOCKS_REQUIRED(work_steal_lock_); 17402b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier 17502b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier friend class WorkStealingWorker; 17602b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier}; 17702b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier 1780e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier} // namespace art 1790e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier 1800e4627e593bc39f8e3d89c31f8977d55054c07ccMathieu Chartier#endif // ART_SRC_THREAD_POOL_H_ 181