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_ |