Fix clang error caused by lack of OVERRIDE in r161270.
[chromium-blink-merge.git] / base / threading / sequenced_worker_pool.h
blob72abd2bd11ff6dcf9970df55c4db352e836a4688
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef BASE_THREADING_SEQUENCED_WORKER_POOL_H_
6 #define BASE_THREADING_SEQUENCED_WORKER_POOL_H_
8 #include <cstddef>
9 #include <string>
11 #include "base/base_export.h"
12 #include "base/basictypes.h"
13 #include "base/callback_forward.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/task_runner.h"
18 namespace tracked_objects {
19 class Location;
20 } // namespace tracked_objects
22 namespace base {
24 class MessageLoopProxy;
26 template <class T> class DeleteHelper;
28 class SequencedTaskRunner;
30 // A worker thread pool that enforces ordering between sets of tasks. It also
31 // allows you to specify what should happen to your tasks on shutdown.
33 // To enforce ordering, get a unique sequence token from the pool and post all
34 // tasks you want to order with the token. All tasks with the same token are
35 // guaranteed to execute serially, though not necessarily on the same thread.
37 // Example:
38 // SequencedWorkerPool::SequenceToken token = pool.GetSequenceToken();
39 // pool.PostSequencedWorkerTask(token, SequencedWorkerPool::SKIP_ON_SHUTDOWN,
40 // FROM_HERE, base::Bind(...));
41 // pool.PostSequencedWorkerTask(token, SequencedWorkerPool::SKIP_ON_SHUTDOWN,
42 // FROM_HERE, base::Bind(...));
44 // You can make named sequence tokens to make it easier to share a token
45 // across different components.
47 // You can also post tasks to the pool without ordering using PostWorkerTask.
48 // These will be executed in an unspecified order. The order of execution
49 // between tasks with different sequence tokens is also unspecified.
51 // This class is designed to be leaked on shutdown to allow the
52 // CONTINUE_ON_SHUTDOWN behavior to be implemented. To enforce the
53 // BLOCK_SHUTDOWN behavior, you must call Shutdown() which will wait until
54 // the necessary tasks have completed.
56 // Implementation note: This does not use a base::WorkerPool since that does
57 // not enforce shutdown semantics or allow us to specify how many worker
58 // threads to run. For the typical use case of random background work, we don't
59 // necessarily want to be super aggressive about creating threads.
61 // Note that SequencedWorkerPool is RefCountedThreadSafe (inherited
62 // from TaskRunner).
63 class BASE_EXPORT SequencedWorkerPool : public TaskRunner {
64 public:
65 // Defines what should happen to a task posted to the worker pool on
66 // shutdown.
67 enum WorkerShutdown {
68 // Tasks posted with this mode which have not run at shutdown will be
69 // deleted rather than run, and any tasks with this mode running at
70 // shutdown will be ignored (the worker thread will not be joined).
72 // This option provides a nice way to post stuff you don't want blocking
73 // shutdown. For example, you might be doing a slow DNS lookup and if it's
74 // blocked on the OS, you may not want to stop shutdown, since the result
75 // doesn't really matter at that point.
77 // However, you need to be very careful what you do in your callback when
78 // you use this option. Since the thread will continue to run until the OS
79 // terminates the process, the app can be in the process of tearing down
80 // when you're running. This means any singletons or global objects you
81 // use may suddenly become invalid out from under you. For this reason,
82 // it's best to use this only for slow but simple operations like the DNS
83 // example.
84 CONTINUE_ON_SHUTDOWN,
86 // Tasks posted with this mode that have not started executing at
87 // shutdown will be deleted rather than executed. However, any tasks that
88 // have already begun executing when shutdown is called will be allowed
89 // to continue, and will block shutdown until completion.
91 // Note: Because Shutdown() may block while these tasks are executing,
92 // care must be taken to ensure that they do not block on the thread that
93 // called Shutdown(), as this may lead to deadlock.
94 SKIP_ON_SHUTDOWN,
96 // Tasks posted with this mode will block shutdown until they're
97 // executed. Since this can have significant performance implications,
98 // use sparingly.
100 // Generally, this should be used only for user data, for example, a task
101 // writing a preference file.
103 // If a task is posted during shutdown, it will not get run since the
104 // workers may already be stopped. In this case, the post operation will
105 // fail (return false) and the task will be deleted.
106 BLOCK_SHUTDOWN,
109 // Opaque identifier that defines sequencing of tasks posted to the worker
110 // pool.
111 class SequenceToken {
112 public:
113 SequenceToken() : id_(0) {}
114 ~SequenceToken() {}
116 bool Equals(const SequenceToken& other) const {
117 return id_ == other.id_;
120 private:
121 friend class SequencedWorkerPool;
123 explicit SequenceToken(int id) : id_(id) {}
125 int id_;
128 // Allows tests to perform certain actions.
129 class TestingObserver {
130 public:
131 virtual ~TestingObserver() {}
132 virtual void OnHasWork() = 0;
133 virtual void WillWaitForShutdown() = 0;
134 virtual void OnDestruct() = 0;
137 // When constructing a SequencedWorkerPool, there must be a
138 // MessageLoop on the current thread unless you plan to deliberately
139 // leak it.
141 // Pass the maximum number of threads (they will be lazily created as needed)
142 // and a prefix for the thread name to aid in debugging.
143 SequencedWorkerPool(size_t max_threads,
144 const std::string& thread_name_prefix);
146 // Like above, but with |observer| for testing. Does not take
147 // ownership of |observer|.
148 SequencedWorkerPool(size_t max_threads,
149 const std::string& thread_name_prefix,
150 TestingObserver* observer);
152 // Returns a unique token that can be used to sequence tasks posted to
153 // PostSequencedWorkerTask(). Valid tokens are alwys nonzero.
154 SequenceToken GetSequenceToken();
156 // Returns the sequence token associated with the given name. Calling this
157 // function multiple times with the same string will always produce the
158 // same sequence token. If the name has not been used before, a new token
159 // will be created.
160 SequenceToken GetNamedSequenceToken(const std::string& name);
162 // Returns a SequencedTaskRunner wrapper which posts to this
163 // SequencedWorkerPool using the given sequence token. Tasks with nonzero
164 // delay are posted with SKIP_ON_SHUTDOWN behavior and tasks with zero delay
165 // are posted with BLOCK_SHUTDOWN behavior.
166 scoped_refptr<SequencedTaskRunner> GetSequencedTaskRunner(
167 SequenceToken token);
169 // Returns a SequencedTaskRunner wrapper which posts to this
170 // SequencedWorkerPool using the given sequence token. Tasks with nonzero
171 // delay are posted with SKIP_ON_SHUTDOWN behavior and tasks with zero delay
172 // are posted with the given shutdown behavior.
173 scoped_refptr<SequencedTaskRunner> GetSequencedTaskRunnerWithShutdownBehavior(
174 SequenceToken token,
175 WorkerShutdown shutdown_behavior);
177 // Returns a TaskRunner wrapper which posts to this SequencedWorkerPool using
178 // the given shutdown behavior. Tasks with nonzero delay are posted with
179 // SKIP_ON_SHUTDOWN behavior and tasks with zero delay are posted with the
180 // given shutdown behavior.
181 scoped_refptr<TaskRunner> GetTaskRunnerWithShutdownBehavior(
182 WorkerShutdown shutdown_behavior);
184 // Posts the given task for execution in the worker pool. Tasks posted with
185 // this function will execute in an unspecified order on a background thread.
186 // Returns true if the task was posted. If your tasks have ordering
187 // requirements, see PostSequencedWorkerTask().
189 // This class will attempt to delete tasks that aren't run
190 // (non-block-shutdown semantics) but can't guarantee that this happens. If
191 // all worker threads are busy running CONTINUE_ON_SHUTDOWN tasks, there
192 // will be no workers available to delete these tasks. And there may be
193 // tasks with the same sequence token behind those CONTINUE_ON_SHUTDOWN
194 // tasks. Deleting those tasks before the previous one has completed could
195 // cause nondeterministic crashes because the task could be keeping some
196 // objects alive which do work in their destructor, which could voilate the
197 // assumptions of the running task.
199 // The task will be guaranteed to run to completion before shutdown
200 // (BLOCK_SHUTDOWN semantics).
202 // Returns true if the task was posted successfully. This may fail during
203 // shutdown regardless of the specified ShutdownBehavior.
204 bool PostWorkerTask(const tracked_objects::Location& from_here,
205 const Closure& task);
207 // Same as PostWorkerTask but allows a delay to be specified (although doing
208 // so changes the shutdown behavior). The task will be run after the given
209 // delay has elapsed.
211 // If the delay is nonzero, the task won't be guaranteed to run to completion
212 // before shutdown (SKIP_ON_SHUTDOWN semantics) to avoid shutdown hangs.
213 // If the delay is zero, this behaves exactly like PostWorkerTask, i.e. the
214 // task will be guaranteed to run to completion before shutdown
215 // (BLOCK_SHUTDOWN semantics).
216 bool PostDelayedWorkerTask(const tracked_objects::Location& from_here,
217 const Closure& task,
218 TimeDelta delay);
220 // Same as PostWorkerTask but allows specification of the shutdown behavior.
221 bool PostWorkerTaskWithShutdownBehavior(
222 const tracked_objects::Location& from_here,
223 const Closure& task,
224 WorkerShutdown shutdown_behavior);
226 // Like PostWorkerTask above, but provides sequencing semantics. This means
227 // that tasks posted with the same sequence token (see GetSequenceToken())
228 // are guaranteed to execute in order. This is useful in cases where you're
229 // doing operations that may depend on previous ones, like appending to a
230 // file.
232 // The task will be guaranteed to run to completion before shutdown
233 // (BLOCK_SHUTDOWN semantics).
235 // Returns true if the task was posted successfully. This may fail during
236 // shutdown regardless of the specified ShutdownBehavior.
237 bool PostSequencedWorkerTask(SequenceToken sequence_token,
238 const tracked_objects::Location& from_here,
239 const Closure& task);
241 // Like PostSequencedWorkerTask above, but allows you to specify a named
242 // token, which saves an extra call to GetNamedSequenceToken.
243 bool PostNamedSequencedWorkerTask(const std::string& token_name,
244 const tracked_objects::Location& from_here,
245 const Closure& task);
247 // Same as PostSequencedWorkerTask but allows a delay to be specified
248 // (although doing so changes the shutdown behavior). The task will be run
249 // after the given delay has elapsed.
251 // If the delay is nonzero, the task won't be guaranteed to run to completion
252 // before shutdown (SKIP_ON_SHUTDOWN semantics) to avoid shutdown hangs.
253 // If the delay is zero, this behaves exactly like PostSequencedWorkerTask,
254 // i.e. the task will be guaranteed to run to completion before shutdown
255 // (BLOCK_SHUTDOWN semantics).
256 bool PostDelayedSequencedWorkerTask(
257 SequenceToken sequence_token,
258 const tracked_objects::Location& from_here,
259 const Closure& task,
260 TimeDelta delay);
262 // Same as PostSequencedWorkerTask but allows specification of the shutdown
263 // behavior.
264 bool PostSequencedWorkerTaskWithShutdownBehavior(
265 SequenceToken sequence_token,
266 const tracked_objects::Location& from_here,
267 const Closure& task,
268 WorkerShutdown shutdown_behavior);
270 // TaskRunner implementation. Forwards to PostDelayedWorkerTask().
271 virtual bool PostDelayedTask(const tracked_objects::Location& from_here,
272 const Closure& task,
273 TimeDelta delay) OVERRIDE;
274 virtual bool RunsTasksOnCurrentThread() const OVERRIDE;
276 // Returns true if the current thread is processing a task with the given
277 // sequence_token.
278 bool IsRunningSequenceOnCurrentThread(SequenceToken sequence_token) const;
280 // Blocks until all pending tasks are complete. This should only be called in
281 // unit tests when you want to validate something that should have happened.
283 // Note that calling this will not prevent other threads from posting work to
284 // the queue while the calling thread is waiting on Flush(). In this case,
285 // Flush will return only when there's no more work in the queue. Normally,
286 // this doesn't come up since in a test, all the work is being posted from
287 // the main thread.
288 void FlushForTesting();
290 // Spuriously signal that there is work to be done.
291 void SignalHasWorkForTesting();
293 // Implements the worker pool shutdown. This should be called during app
294 // shutdown, and will discard/join with appropriate tasks before returning.
295 // After this call, subsequent calls to post tasks will fail.
297 // Must be called from the same thread this object was constructed on.
298 void Shutdown();
300 protected:
301 virtual ~SequencedWorkerPool();
303 virtual void OnDestruct() const OVERRIDE;
305 private:
306 friend class RefCountedThreadSafe<SequencedWorkerPool>;
307 friend class DeleteHelper<SequencedWorkerPool>;
309 class Inner;
310 class Worker;
312 const scoped_refptr<MessageLoopProxy> constructor_message_loop_;
314 // Avoid pulling in too many headers by putting (almost) everything
315 // into |inner_|.
316 const scoped_ptr<Inner> inner_;
318 DISALLOW_COPY_AND_ASSIGN(SequencedWorkerPool);
321 } // namespace base
323 #endif // BASE_THREADING_SEQUENCED_WORKER_POOL_H_