15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The thread pool used in the POSIX implementation of WorkerPool dynamically 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// adds threads as necessary to handle all tasks. It keeps old threads around 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for a period of time to allow them to be reused. After this waiting period, 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the threads exit. This thread pool uses non-joinable threads, therefore 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// worker threads are not joined during process shutdown. This means that 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// potentially long running tasks (such as DNS lookup) do not block process 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// shutdown, but also means that process shutdown may "leak" objects. Note that 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// although PosixDynamicThreadPool spawns the worker threads and manages the 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// task queue, it does not own the worker threads. The worker threads ask the 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PosixDynamicThreadPool for work and eventually clean themselves up. The 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// worker threads all maintain scoped_refptrs to the PosixDynamicThreadPool 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// instance, which prevents PosixDynamicThreadPool from disappearing before all 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// worker threads exit. The owner of PosixDynamicThreadPool should likewise 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// maintain a scoped_refptr to the PosixDynamicThreadPool instance. 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NOTE: The classes defined in this file are only meant for use by the POSIX 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// implementation of WorkerPool. No one else should be using these classes. 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These symbols are exported in a header purely for testing purposes. 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef BASE_THREADING_WORKER_POOL_POSIX_H_ 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BASE_THREADING_WORKER_POOL_POSIX_H_ 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <queue> 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback_forward.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/location.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/pending_task.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/condition_variable.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/platform_thread.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/tracked_objects.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Task; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BASE_EXPORT PosixDynamicThreadPool 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : public RefCountedThreadSafe<PosixDynamicThreadPool> { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class PosixDynamicThreadPoolPeer; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // All worker threads will share the same |name_prefix|. They will exit after 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |idle_seconds_before_exit|. 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PosixDynamicThreadPool(const std::string& name_prefix, 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int idle_seconds_before_exit); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Indicates that the thread pool is going away. Stops handing out tasks to 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // worker threads. Wakes up all the idle threads to let them exit. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Terminate(); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Adds |task| to the thread pool. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void PostTask(const tracked_objects::Location& from_here, 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Closure& task); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Worker thread method to wait for up to |idle_seconds_before_exit| for more 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // work from the thread pool. Returns NULL if no work is available. 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PendingTask WaitForTask(); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class RefCountedThreadSafe<PosixDynamicThreadPool>; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class PosixDynamicThreadPoolPeer; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~PosixDynamicThreadPool(); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Adds pending_task to the thread pool. This function will clear 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |pending_task->task|. 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void AddTask(PendingTask* pending_task); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string name_prefix_; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int idle_seconds_before_exit_; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Lock lock_; // Protects all the variables below. 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Signal()s worker threads to let them know more tasks are available. 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Also used for Broadcast()'ing to worker threads to let them know the pool 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is being deleted and they can exit. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ConditionVariable pending_tasks_available_cv_; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_idle_threads_; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TaskQueue pending_tasks_; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool terminated_; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only used for tests to ensure correct thread ordering. It will always be 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NULL in non-test code. 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<ConditionVariable> num_idle_threads_cv_; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(PosixDynamicThreadPool); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // BASE_THREADING_WORKER_POOL_POSIX_H_ 99