1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Copyright (c) 2009 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The thread pool used in the Linux implementation of WorkerPool dynamically
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// adds threads as necessary to handle all tasks.  It keeps old threads around
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// for a period of time to allow them to be reused.  After this waiting period,
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// the threads exit.  This thread pool uses non-joinable threads, therefore
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// worker threads are not joined during process shutdown.  This means that
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// potentially long running tasks (such as DNS lookup) do not block process
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// shutdown, but also means that process shutdown may "leak" objects.  Note that
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// although LinuxDynamicThreadPool spawns the worker threads and manages the
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// task queue, it does not own the worker threads.  The worker threads ask the
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// LinuxDynamicThreadPool for work and eventually clean themselves up.  The
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// worker threads all maintain scoped_refptrs to the LinuxDynamicThreadPool
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// instance, which prevents LinuxDynamicThreadPool from disappearing before all
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// worker threads exit.  The owner of LinuxDynamicThreadPool should likewise
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// maintain a scoped_refptr to the LinuxDynamicThreadPool instance.
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// NOTE: The classes defined in this file are only meant for use by the Linux
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// implementation of WorkerPool.  No one else should be using these classes.
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// These symbols are exported in a header purely for testing purposes.
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifndef BASE_WORKER_POOL_LINUX_H_
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define BASE_WORKER_POOL_LINUX_H_
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <queue>
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <string>
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/basictypes.h"
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/condition_variable.h"
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/lock.h"
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/platform_thread.h"
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/ref_counted.h"
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/scoped_ptr.h"
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass Task;
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace base {
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass LinuxDynamicThreadPool
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    : public RefCountedThreadSafe<LinuxDynamicThreadPool> {
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  class LinuxDynamicThreadPoolPeer;
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // All worker threads will share the same |name_prefix|.  They will exit after
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // |idle_seconds_before_exit|.
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LinuxDynamicThreadPool(const std::string& name_prefix,
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                         int idle_seconds_before_exit);
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ~LinuxDynamicThreadPool();
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Indicates that the thread pool is going away.  Stops handing out tasks to
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // worker threads.  Wakes up all the idle threads to let them exit.
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void Terminate();
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Adds |task| to the thread pool.  LinuxDynamicThreadPool assumes ownership
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // of |task|.
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void PostTask(Task* task);
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Worker thread method to wait for up to |idle_seconds_before_exit| for more
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // work from the thread pool.  Returns NULL if no work is available.
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Task* WaitForTask();
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  friend class LinuxDynamicThreadPoolPeer;
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const std::string name_prefix_;
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const int idle_seconds_before_exit_;
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Lock lock_;  // Protects all the variables below.
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Signal()s worker threads to let them know more tasks are available.
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Also used for Broadcast()'ing to worker threads to let them know the pool
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // is being deleted and they can exit.
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ConditionVariable tasks_available_cv_;
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int num_idle_threads_;
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::queue<Task*> tasks_;
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool terminated_;
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Only used for tests to ensure correct thread ordering.  It will always be
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // NULL in non-test code.
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_ptr<ConditionVariable> num_idle_threads_cv_;
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DISALLOW_COPY_AND_ASSIGN(LinuxDynamicThreadPool);
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace base
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif  // BASE_WORKER_POOL_LINUX_H_
89