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