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

Unified Diff: base/worker_pool_job.h

Issue 5710002: Create base::WorkerPoolJob. Use it for HostResolverImpl and DirectoryLister. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address comments. Created 10 years 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
Index: base/worker_pool_job.h
diff --git a/base/worker_pool_job.h b/base/worker_pool_job.h
new file mode 100644
index 0000000000000000000000000000000000000000..9f766fa60e4d4a9ec0c394d14a936e76f005123b
--- /dev/null
+++ b/base/worker_pool_job.h
@@ -0,0 +1,118 @@
+// Copyright (c) 2010 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.
+
+#ifndef BASE_WORKER_POOL_JOB_H_
+#define BASE_WORKER_POOL_JOB_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/lock.h"
+#include "base/message_loop_proxy.h"
+#include "base/ref_counted.h"
+#include "base/thread_checker.h"
+
+namespace base {
+
+// WARNING: Are you sure you want to use WorkerPool in the first place? The
+// thread will _not_ be joined, so the job may still be running during shutdown.
+// Global objects that are deleted by AtExitManager should not be accessed on
+// the WorkerPool thread, otherwise there is potential for shutdown crashes.
+//
+// WorkerPoolJob is a helper class for implementing jobs that get created on an
+// origin thread, get posted to run on a WorkerPool thread, and then run back on
+// the origin thread upon completion. WorkerPoolJob also handles cancellation
+// of a job which prevents it from calling back. Note that we use inheritance
+// rather than composition here, since WorkerPoolJob also handles lifetime
+// management via refcounting.
+class WorkerPoolJob : public base::RefCountedThreadSafe<WorkerPoolJob> {
+ public:
+ // ScopedHandle is provided to automate cancellation of the WorkerPoolJob.
+ template <typename JobType>
+ class ScopedHandle {
+ public:
+ explicit ScopedHandle(JobType* job) : job_(job) {}
+
+ ~ScopedHandle() {
+ if (!job_->canceled() && job_->state_ == RUNNING)
+ job_->CancelJob();
+ }
+
+ JobType* job() const { return job_.get(); }
+
+ private:
+ const scoped_refptr<JobType> job_;
+ DISALLOW_COPY_AND_ASSIGN(ScopedHandle);
+ };
+
+ protected:
+ WorkerPoolJob();
+
+ // This may be deleted on the origin or worker thread.
+ virtual ~WorkerPoolJob();
+
+ // Starts the job. Will post itself to the WorkerPool, where it will invoke
+ // RunJob(). After RunJob() runs, it will post itself back to the origin
+ // thread, where it will invoke OnJobCompleted(). This can only be called
+ // once and must be called on the origin thread.
+ void StartJob();
+
+ // Cancels the job. OnJobCompleted() is guaranteed not to be called when this
+ // happens. May only be called once, and only on the origin thread.
+ void CancelJob();
+
+ // Returns true if CancelJob() has been called.
+ bool canceled() const;
+
+ // NOTE(willchan): I've restricted this to unit tests only, primarily because
+ // I haven't found a good reason for allowing subtypes to access this. If
+ // there is a motivating reason to do so, I am open to it.
+#if defined(UNIT_TEST)
+ scoped_refptr<MessageLoopProxy> origin_loop() const {
+ return origin_loop_;
+ }
+
+ // Returns true if OnJobCompleted() has not been called yet.
+ bool is_running() const {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_NE(state_, NONE);
+ return state_ == RUNNING;
+ }
+#endif // defined(UNIT_TEST)
+
+ private:
+ friend class base::RefCountedThreadSafe<WorkerPoolJob>;
+
+ // State machine, primarily for enforcing that certain events only happen
+ // once. Also lets us implement is_running().
+ enum State {
+ NONE,
+ RUNNING,
+ DONE,
+ };
+
+ // API for subtypes to implement.
+
+ // RunJob() runs on the worker thread. If CancelJob() is called on the origin
+ // thread , then it may never be invoked, but that's a race.
+ virtual void RunJob() = 0;
+
+ // OnJobCompleted() runs on the origin thread. If CancelJob() is called, then
+ // it may never be invoked.
eroman 2011/01/05 01:24:52 This wording can be stronger. If CancelJob() was c
+ virtual void OnJobCompleted() = 0;
+
+ void RunJobOnWorkerPool();
+ void CompleteJobOnOriginLoop();
+
+ ThreadChecker thread_checker_;
+ const scoped_refptr<MessageLoopProxy> origin_loop_;
+
+ bool canceled_;
+ State state_;
+
+ DISALLOW_COPY_AND_ASSIGN(WorkerPoolJob);
+};
+
+} // namespace base
+
+#endif // BASE_WORKER_POOL_JOB_H_
« no previous file with comments | « base/i18n/file_util_icu.cc ('k') | base/worker_pool_job.cc » ('j') | base/worker_pool_job.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698