Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4581)

Unified Diff: base/threading/sequenced_worker_pool.h

Issue 9347056: Fix up SequencedWorkerPool in preparation for making it a TaskRunner (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address dom_storage comments Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | base/threading/sequenced_worker_pool.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/threading/sequenced_worker_pool.h
diff --git a/base/threading/sequenced_worker_pool.h b/base/threading/sequenced_worker_pool.h
index f5770a72b966e21bf56cfadc15de3edb0ea36877..2bd3d581f5fb52eeac54c9d8ca229df9f115c603 100644
--- a/base/threading/sequenced_worker_pool.h
+++ b/base/threading/sequenced_worker_pool.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -6,13 +6,22 @@
#define BASE_THREADING_SEQUENCED_WORKER_POOL_H_
#pragma once
+#include <cstddef>
+#include <list>
+#include <map>
+#include <set>
#include <string>
+#include <vector>
+#include "base/atomicops.h"
+#include "base/base_export.h"
+#include "base/basictypes.h"
#include "base/callback.h"
#include "base/memory/linked_ptr.h"
#include "base/memory/ref_counted.h"
+#include "base/synchronization/condition_variable.h"
brettw 2012/02/24 05:43:34 One of the reasons I liked the inner class was tha
+#include "base/synchronization/lock.h"
#include "base/tracked_objects.h"
-#include "base/base_export.h"
namespace base {
@@ -46,7 +55,8 @@ namespace base {
// not enforce shutdown semantics or allow us to specify how many worker
// threads to run. For the typical use case of random background work, we don't
// necessarily want to be super aggressive about creating threads.
-class BASE_EXPORT SequencedWorkerPool {
+class BASE_EXPORT SequencedWorkerPool
+ : public RefCountedThreadSafe<SequencedWorkerPool> {
public:
// Defines what should happen to a task posted to the worker pool on shutdown.
enum WorkerShutdown {
@@ -87,10 +97,10 @@ class BASE_EXPORT SequencedWorkerPool {
};
// Opaque identifier that defines sequencing of tasks posted to the worker
- // pool. See NewSequenceToken().
+ // pool.
class SequenceToken {
public:
- explicit SequenceToken() : id_(0) {}
+ SequenceToken() : id_(0) {}
~SequenceToken() {}
bool Equals(const SequenceToken& other) const {
@@ -100,7 +110,7 @@ class BASE_EXPORT SequencedWorkerPool {
private:
friend class SequencedWorkerPool;
- SequenceToken(int id) : id_(id) {}
+ explicit SequenceToken(int id) : id_(id) {}
int id_;
};
@@ -116,7 +126,6 @@ class BASE_EXPORT SequencedWorkerPool {
// and a prefix for the thread name to ad in debugging.
SequencedWorkerPool(size_t max_threads,
const std::string& thread_name_prefix);
- ~SequencedWorkerPool();
// Returns a unique token that can be used to sequence tasks posted to
// PostSequencedWorkerTask(). Valid tokens are alwys nonzero.
@@ -149,12 +158,12 @@ class BASE_EXPORT SequencedWorkerPool {
// Returns true if the task was posted successfully. This may fail during
// shutdown regardless of the specified ShutdownBehavior.
bool PostWorkerTask(const tracked_objects::Location& from_here,
- const base::Closure& task);
+ const Closure& task);
// Same as PostWorkerTask but allows specification of the shutdown behavior.
bool PostWorkerTaskWithShutdownBehavior(
const tracked_objects::Location& from_here,
- const base::Closure& task,
+ const Closure& task,
WorkerShutdown shutdown_behavior);
// Like PostWorkerTask above, but provides sequencing semantics. This means
@@ -170,20 +179,20 @@ class BASE_EXPORT SequencedWorkerPool {
// shutdown regardless of the specified ShutdownBehavior.
bool PostSequencedWorkerTask(SequenceToken sequence_token,
const tracked_objects::Location& from_here,
- const base::Closure& task);
+ const Closure& task);
// Like PostSequencedWorkerTask above, but allows you to specify a named
// token, which saves an extra call to GetNamedSequenceToken.
bool PostNamedSequencedWorkerTask(const std::string& token_name,
const tracked_objects::Location& from_here,
- const base::Closure& task);
+ const Closure& task);
// Same as PostSequencedWorkerTask but allows specification of the shutdown
// behavior.
bool PostSequencedWorkerTaskWithShutdownBehavior(
SequenceToken sequence_token,
const tracked_objects::Location& from_here,
- const base::Closure& task,
+ const Closure& task,
WorkerShutdown shutdown_behavior);
// Blocks until all pending tasks are complete. This should only be called in
@@ -206,13 +215,135 @@ class BASE_EXPORT SequencedWorkerPool {
void SetTestingObserver(TestingObserver* observer);
private:
- class Inner;
+ friend class RefCountedThreadSafe<SequencedWorkerPool>;
class Worker;
- friend class Inner;
- friend class Worker;
+ struct SequencedTask {
+ SequencedTask();
+ ~SequencedTask();
+
+ int sequence_token_id;
+ WorkerShutdown shutdown_behavior;
+ tracked_objects::Location location;
+ Closure task;
+ };
+
+ ~SequencedWorkerPool();
+
+ // This function accepts a name and an ID. If the name is null, the
+ // token ID is used. This allows us to implement the optional name lookup
+ // from a single function without having to enter the lock a separate time.
+ bool PostTaskHelper(const std::string* optional_token_name,
+ SequenceToken sequence_token,
+ WorkerShutdown shutdown_behavior,
+ const tracked_objects::Location& from_here,
+ const Closure& task);
+
+ // Runs the worker loop on the background thread.
+ void ThreadLoop(Worker* this_worker);
+
+ // Called from within the lock, this converts the given token name into a
+ // token ID, creating a new one if necessary.
+ int LockedGetNamedTokenID(const std::string& name);
+
+ // The calling code should clear the given delete_these_oustide_lock
+ // vector the next time the lock is released. See the implementation for
+ // a more detailed description.
+ bool GetWork(SequencedTask* task,
+ std::vector<Closure>* delete_these_outside_lock);
+
+ // Peforms init and cleanup around running the given task. WillRun...
+ // returns the value from PrepareToStartAdditionalThreadIfNecessary.
+ // The calling code should call FinishStartingAdditionalThread once the
+ // lock is released if the return values is nonzero.
+ int WillRunWorkerTask(const SequencedTask& task);
+ void DidRunWorkerTask(const SequencedTask& task);
+
+ // Returns true if there are no threads currently running the given
+ // sequence token.
+ bool IsSequenceTokenRunnable(int sequence_token_id) const;
+
+ // Checks if all threads are busy and the addition of one more could run an
+ // additional task waiting in the queue. This must be called from within
+ // the lock.
+ //
+ // If another thread is helpful, this will mark the thread as being in the
+ // process of starting and returns the index of the new thread which will be
+ // 0 or more. The caller should then call FinishStartingAdditionalThread to
+ // complete initialization once the lock is released.
+ //
+ // If another thread is not necessary, returne 0;
+ //
+ // See the implementedion for more.
+ int PrepareToStartAdditionalThreadIfHelpful();
+
+ // The second part of thread creation after
+ // PrepareToStartAdditionalThreadIfHelpful with the thread number it
+ // generated. This actually creates the thread and should be called outside
+ // the lock to avoid blocking important work starting a thread in the lock.
+ void FinishStartingAdditionalThread(int thread_number);
+
+ // Checks whether there is work left that's blocking shutdown. Must be
+ // called inside the lock.
+ bool CanShutdown() const;
+
+ // The last sequence number used. Managed by GetSequenceToken, since this
+ // only does threadsafe increment operations, you do not need to hold the
+ // lock.
+ volatile subtle::Atomic32 last_sequence_number_;
+
+ // This lock protects |everything in this class|. Do not read or modify
+ // anything without holding this lock. Do not block while holding this
+ // lock.
+ Lock lock_;
+
+ // Condition variable used to wake up worker threads when a task is runnable.
+ ConditionVariable cond_var_;
+
+ // The maximum number of worker threads we'll create.
+ size_t max_threads_;
+
+ std::string thread_name_prefix_;
+
+ // Associates all known sequence token names with their IDs.
+ std::map<std::string, int> named_sequence_tokens_;
+
+ // Owning pointers to all threads we've created so far. Since we lazily
+ // create threads, this may be less than max_threads_ and will be initially
+ // empty.
+ std::vector<linked_ptr<Worker> > threads_;
+
+ // Set to true when we're in the process of creating another thread.
+ // See PrepareToStartAdditionalThreadIfHelpful for more.
+ bool thread_being_created_;
+
+ // Number of threads currently waiting for work.
+ size_t waiting_thread_count_;
+
+ // Number of threads currently running tasks that have the BLOCK_SHUTDOWN
+ // flag set.
+ size_t blocking_shutdown_thread_count_;
+
+ // In-order list of all pending tasks. These are tasks waiting for a thread
+ // to run on or that are blocked on a previous task in their sequence.
+ //
+ // We maintain the pending_task_count_ separately for metrics because
+ // list.size() can be linear time.
+ std::list<SequencedTask> pending_tasks_;
+ size_t pending_task_count_;
+
+ // Number of tasks in the pending_tasks_ list that are marked as blocking
+ // shutdown.
+ size_t blocking_shutdown_pending_task_count_;
+
+ // Lists all sequence tokens currently executing.
+ std::set<int> current_sequences_;
+
+ // Set when Shutdown is called and no further tasks should be
+ // allowed, though we may still be running existing tasks.
+ bool shutdown_called_;
- scoped_refptr<Inner> inner_;
+ TestingObserver* testing_observer_;
DISALLOW_COPY_AND_ASSIGN(SequencedWorkerPool);
};
« no previous file with comments | « no previous file | base/threading/sequenced_worker_pool.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698