| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef BASE_THREADING_SEQUENCED_WORKER_POOL_H_ | 5 #ifndef BASE_THREADING_SEQUENCED_WORKER_POOL_H_ |
| 6 #define BASE_THREADING_SEQUENCED_WORKER_POOL_H_ | 6 #define BASE_THREADING_SEQUENCED_WORKER_POOL_H_ |
| 7 #pragma once | 7 #pragma once |
| 8 | 8 |
| 9 #include <cstddef> |
| 9 #include <string> | 10 #include <string> |
| 10 | 11 |
| 11 #include "base/callback.h" | 12 #include "base/base_export.h" |
| 12 #include "base/memory/linked_ptr.h" | 13 #include "base/basictypes.h" |
| 14 #include "base/callback_forward.h" |
| 13 #include "base/memory/ref_counted.h" | 15 #include "base/memory/ref_counted.h" |
| 14 #include "base/tracked_objects.h" | 16 #include "base/memory/scoped_ptr.h" |
| 15 #include "base/base_export.h" | 17 |
| 18 namespace tracked_objects { |
| 19 class Location; |
| 20 } // namespace tracked_objects |
| 16 | 21 |
| 17 namespace base { | 22 namespace base { |
| 18 | 23 |
| 19 // A worker thread pool that enforces ordering between sets of tasks. It also | 24 // A worker thread pool that enforces ordering between sets of tasks. It also |
| 20 // allows you to specify what should happen to your tasks on shutdown. | 25 // allows you to specify what should happen to your tasks on shutdown. |
| 21 // | 26 // |
| 22 // To enforce ordering, get a unique sequence token from the pool and post all | 27 // To enforce ordering, get a unique sequence token from the pool and post all |
| 23 // tasks you want to order with the token. All tasks with the same token are | 28 // tasks you want to order with the token. All tasks with the same token are |
| 24 // guaranteed to execute serially, though not necessarily on the same thread. | 29 // guaranteed to execute serially, though not necessarily on the same thread. |
| 25 // | 30 // |
| (...skipping 13 matching lines...) Expand all Loading... |
| 39 // | 44 // |
| 40 // This class is designed to be leaked on shutdown to allow the | 45 // This class is designed to be leaked on shutdown to allow the |
| 41 // CONTINUE_ON_SHUTDOWN behavior to be implemented. To enforce the | 46 // CONTINUE_ON_SHUTDOWN behavior to be implemented. To enforce the |
| 42 // BLOCK_SHUTDOWN behavior, you must call Shutdown() which will wait until | 47 // BLOCK_SHUTDOWN behavior, you must call Shutdown() which will wait until |
| 43 // the necessary tasks have completed. | 48 // the necessary tasks have completed. |
| 44 // | 49 // |
| 45 // Implementation note: This does not use a base::WorkerPool since that does | 50 // Implementation note: This does not use a base::WorkerPool since that does |
| 46 // not enforce shutdown semantics or allow us to specify how many worker | 51 // not enforce shutdown semantics or allow us to specify how many worker |
| 47 // threads to run. For the typical use case of random background work, we don't | 52 // threads to run. For the typical use case of random background work, we don't |
| 48 // necessarily want to be super aggressive about creating threads. | 53 // necessarily want to be super aggressive about creating threads. |
| 49 class BASE_EXPORT SequencedWorkerPool { | 54 class BASE_EXPORT SequencedWorkerPool |
| 55 : public RefCountedThreadSafe<SequencedWorkerPool> { |
| 50 public: | 56 public: |
| 51 // Defines what should happen to a task posted to the worker pool on shutdown. | 57 // Defines what should happen to a task posted to the worker pool on shutdown. |
| 52 enum WorkerShutdown { | 58 enum WorkerShutdown { |
| 53 // Tasks posted with this mode which have not run at shutdown will be | 59 // Tasks posted with this mode which have not run at shutdown will be |
| 54 // deleted rather than run, and any tasks with this mode running at | 60 // deleted rather than run, and any tasks with this mode running at |
| 55 // shutdown will be ignored (the worker thread will not be joined). | 61 // shutdown will be ignored (the worker thread will not be joined). |
| 56 // | 62 // |
| 57 // This option provides a nice way to post stuff you don't want blocking | 63 // This option provides a nice way to post stuff you don't want blocking |
| 58 // shutdown. For example, you might be doing a slow DNS lookup and if it's | 64 // shutdown. For example, you might be doing a slow DNS lookup and if it's |
| 59 // blocked on the OS, you may not want to stop shutdown, since the result | 65 // blocked on the OS, you may not want to stop shutdown, since the result |
| (...skipping 20 matching lines...) Expand all Loading... |
| 80 // Generally, this should be used only for user data, for example, a task | 86 // Generally, this should be used only for user data, for example, a task |
| 81 // writing a preference file. | 87 // writing a preference file. |
| 82 // | 88 // |
| 83 // If a task is posted during shutdown, it will not get run since the | 89 // If a task is posted during shutdown, it will not get run since the |
| 84 // workers may already be stopped. In this case, the post operation will | 90 // workers may already be stopped. In this case, the post operation will |
| 85 // fail (return false) and the task will be deleted. | 91 // fail (return false) and the task will be deleted. |
| 86 BLOCK_SHUTDOWN, | 92 BLOCK_SHUTDOWN, |
| 87 }; | 93 }; |
| 88 | 94 |
| 89 // Opaque identifier that defines sequencing of tasks posted to the worker | 95 // Opaque identifier that defines sequencing of tasks posted to the worker |
| 90 // pool. See NewSequenceToken(). | 96 // pool. |
| 91 class SequenceToken { | 97 class SequenceToken { |
| 92 public: | 98 public: |
| 93 explicit SequenceToken() : id_(0) {} | 99 SequenceToken() : id_(0) {} |
| 94 ~SequenceToken() {} | 100 ~SequenceToken() {} |
| 95 | 101 |
| 96 bool Equals(const SequenceToken& other) const { | 102 bool Equals(const SequenceToken& other) const { |
| 97 return id_ == other.id_; | 103 return id_ == other.id_; |
| 98 } | 104 } |
| 99 | 105 |
| 100 private: | 106 private: |
| 101 friend class SequencedWorkerPool; | 107 friend class SequencedWorkerPool; |
| 102 | 108 |
| 103 SequenceToken(int id) : id_(id) {} | 109 explicit SequenceToken(int id) : id_(id) {} |
| 104 | 110 |
| 105 int id_; | 111 int id_; |
| 106 }; | 112 }; |
| 107 | 113 |
| 108 // Allows tests to perform certain actions. | 114 // Allows tests to perform certain actions. |
| 109 class TestingObserver { | 115 class TestingObserver { |
| 110 public: | 116 public: |
| 111 virtual ~TestingObserver() {} | 117 virtual ~TestingObserver() {} |
| 112 virtual void WillWaitForShutdown() = 0; | 118 virtual void WillWaitForShutdown() = 0; |
| 113 }; | 119 }; |
| 114 | 120 |
| 115 // Pass the maximum number of threads (they will be lazily created as needed) | 121 // Pass the maximum number of threads (they will be lazily created as needed) |
| 116 // and a prefix for the thread name to ad in debugging. | 122 // and a prefix for the thread name to ad in debugging. |
| 117 SequencedWorkerPool(size_t max_threads, | 123 SequencedWorkerPool(size_t max_threads, |
| 118 const std::string& thread_name_prefix); | 124 const std::string& thread_name_prefix); |
| 119 ~SequencedWorkerPool(); | |
| 120 | 125 |
| 121 // Returns a unique token that can be used to sequence tasks posted to | 126 // Returns a unique token that can be used to sequence tasks posted to |
| 122 // PostSequencedWorkerTask(). Valid tokens are alwys nonzero. | 127 // PostSequencedWorkerTask(). Valid tokens are alwys nonzero. |
| 123 SequenceToken GetSequenceToken(); | 128 SequenceToken GetSequenceToken(); |
| 124 | 129 |
| 125 // Returns the sequence token associated with the given name. Calling this | 130 // Returns the sequence token associated with the given name. Calling this |
| 126 // function multiple times with the same string will always produce the | 131 // function multiple times with the same string will always produce the |
| 127 // same sequence token. If the name has not been used before, a new token | 132 // same sequence token. If the name has not been used before, a new token |
| 128 // will be created. | 133 // will be created. |
| 129 SequenceToken GetNamedSequenceToken(const std::string& name); | 134 SequenceToken GetNamedSequenceToken(const std::string& name); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 142 // cause nondeterministic crashes because the task could be keeping some | 147 // cause nondeterministic crashes because the task could be keeping some |
| 143 // objects alive which do work in their destructor, which could voilate the | 148 // objects alive which do work in their destructor, which could voilate the |
| 144 // assumptions of the running task. | 149 // assumptions of the running task. |
| 145 // | 150 // |
| 146 // The task will be guaranteed to run to completion before shutdown | 151 // The task will be guaranteed to run to completion before shutdown |
| 147 // (BLOCK_SHUTDOWN semantics). | 152 // (BLOCK_SHUTDOWN semantics). |
| 148 // | 153 // |
| 149 // Returns true if the task was posted successfully. This may fail during | 154 // Returns true if the task was posted successfully. This may fail during |
| 150 // shutdown regardless of the specified ShutdownBehavior. | 155 // shutdown regardless of the specified ShutdownBehavior. |
| 151 bool PostWorkerTask(const tracked_objects::Location& from_here, | 156 bool PostWorkerTask(const tracked_objects::Location& from_here, |
| 152 const base::Closure& task); | 157 const Closure& task); |
| 153 | 158 |
| 154 // Same as PostWorkerTask but allows specification of the shutdown behavior. | 159 // Same as PostWorkerTask but allows specification of the shutdown behavior. |
| 155 bool PostWorkerTaskWithShutdownBehavior( | 160 bool PostWorkerTaskWithShutdownBehavior( |
| 156 const tracked_objects::Location& from_here, | 161 const tracked_objects::Location& from_here, |
| 157 const base::Closure& task, | 162 const Closure& task, |
| 158 WorkerShutdown shutdown_behavior); | 163 WorkerShutdown shutdown_behavior); |
| 159 | 164 |
| 160 // Like PostWorkerTask above, but provides sequencing semantics. This means | 165 // Like PostWorkerTask above, but provides sequencing semantics. This means |
| 161 // that tasks posted with the same sequence token (see GetSequenceToken()) | 166 // that tasks posted with the same sequence token (see GetSequenceToken()) |
| 162 // are guaranteed to execute in order. This is useful in cases where you're | 167 // are guaranteed to execute in order. This is useful in cases where you're |
| 163 // doing operations that may depend on previous ones, like appending to a | 168 // doing operations that may depend on previous ones, like appending to a |
| 164 // file. | 169 // file. |
| 165 // | 170 // |
| 166 // The task will be guaranteed to run to completion before shutdown | 171 // The task will be guaranteed to run to completion before shutdown |
| 167 // (BLOCK_SHUTDOWN semantics). | 172 // (BLOCK_SHUTDOWN semantics). |
| 168 // | 173 // |
| 169 // Returns true if the task was posted successfully. This may fail during | 174 // Returns true if the task was posted successfully. This may fail during |
| 170 // shutdown regardless of the specified ShutdownBehavior. | 175 // shutdown regardless of the specified ShutdownBehavior. |
| 171 bool PostSequencedWorkerTask(SequenceToken sequence_token, | 176 bool PostSequencedWorkerTask(SequenceToken sequence_token, |
| 172 const tracked_objects::Location& from_here, | 177 const tracked_objects::Location& from_here, |
| 173 const base::Closure& task); | 178 const Closure& task); |
| 174 | 179 |
| 175 // Like PostSequencedWorkerTask above, but allows you to specify a named | 180 // Like PostSequencedWorkerTask above, but allows you to specify a named |
| 176 // token, which saves an extra call to GetNamedSequenceToken. | 181 // token, which saves an extra call to GetNamedSequenceToken. |
| 177 bool PostNamedSequencedWorkerTask(const std::string& token_name, | 182 bool PostNamedSequencedWorkerTask(const std::string& token_name, |
| 178 const tracked_objects::Location& from_here, | 183 const tracked_objects::Location& from_here, |
| 179 const base::Closure& task); | 184 const Closure& task); |
| 180 | 185 |
| 181 // Same as PostSequencedWorkerTask but allows specification of the shutdown | 186 // Same as PostSequencedWorkerTask but allows specification of the shutdown |
| 182 // behavior. | 187 // behavior. |
| 183 bool PostSequencedWorkerTaskWithShutdownBehavior( | 188 bool PostSequencedWorkerTaskWithShutdownBehavior( |
| 184 SequenceToken sequence_token, | 189 SequenceToken sequence_token, |
| 185 const tracked_objects::Location& from_here, | 190 const tracked_objects::Location& from_here, |
| 186 const base::Closure& task, | 191 const Closure& task, |
| 187 WorkerShutdown shutdown_behavior); | 192 WorkerShutdown shutdown_behavior); |
| 188 | 193 |
| 189 // Blocks until all pending tasks are complete. This should only be called in | 194 // Blocks until all pending tasks are complete. This should only be called in |
| 190 // unit tests when you want to validate something that should have happened. | 195 // unit tests when you want to validate something that should have happened. |
| 191 // | 196 // |
| 192 // Note that calling this will not prevent other threads from posting work to | 197 // Note that calling this will not prevent other threads from posting work to |
| 193 // the queue while the calling thread is waiting on Flush(). In this case, | 198 // the queue while the calling thread is waiting on Flush(). In this case, |
| 194 // Flush will return only when there's no more work in the queue. Normally, | 199 // Flush will return only when there's no more work in the queue. Normally, |
| 195 // this doesn't come up sine in a test, all the work is being posted from | 200 // this doesn't come up sine in a test, all the work is being posted from |
| 196 // the main thread. | 201 // the main thread. |
| 197 void FlushForTesting(); | 202 void FlushForTesting(); |
| 198 | 203 |
| 199 // Implements the worker pool shutdown. This should be called during app | 204 // Implements the worker pool shutdown. This should be called during app |
| 200 // shutdown, and will discard/join with appropriate tasks before returning. | 205 // shutdown, and will discard/join with appropriate tasks before returning. |
| 201 // After this call, subsequent calls to post tasks will fail. | 206 // After this call, subsequent calls to post tasks will fail. |
| 202 void Shutdown(); | 207 void Shutdown(); |
| 203 | 208 |
| 204 // Called by tests to set the testing observer. This is NULL by default | 209 // Called by tests to set the testing observer. This is NULL by default |
| 205 // and ownership of the pointer is kept with the caller. | 210 // and ownership of the pointer is kept with the caller. |
| 206 void SetTestingObserver(TestingObserver* observer); | 211 void SetTestingObserver(TestingObserver* observer); |
| 207 | 212 |
| 208 private: | 213 private: |
| 214 friend class RefCountedThreadSafe<SequencedWorkerPool>; |
| 215 |
| 209 class Inner; | 216 class Inner; |
| 210 class Worker; | 217 class Worker; |
| 211 | 218 |
| 212 friend class Inner; | 219 ~SequencedWorkerPool(); |
| 213 friend class Worker; | |
| 214 | 220 |
| 215 scoped_refptr<Inner> inner_; | 221 // Avoid pulling in too many headers by putting everything into |
| 222 // |inner_|. |
| 223 const scoped_ptr<Inner> inner_; |
| 216 | 224 |
| 217 DISALLOW_COPY_AND_ASSIGN(SequencedWorkerPool); | 225 DISALLOW_COPY_AND_ASSIGN(SequencedWorkerPool); |
| 218 }; | 226 }; |
| 219 | 227 |
| 220 } // namespace base | 228 } // namespace base |
| 221 | 229 |
| 222 #endif // BASE_THREADING_SEQUENCED_WORKER_POOL_H_ | 230 #endif // BASE_THREADING_SEQUENCED_WORKER_POOL_H_ |
| OLD | NEW |