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

Unified Diff: chrome/browser/storage_monitor/schedule.h

Issue 24298002: Media Galleries API: Use Scheduler in MediaGalleriesPreferences initialization. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 3 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
Index: chrome/browser/storage_monitor/schedule.h
diff --git a/chrome/browser/storage_monitor/schedule.h b/chrome/browser/storage_monitor/schedule.h
new file mode 100644
index 0000000000000000000000000000000000000000..0466a7041c2d6ea4541db1df4cca001698c37f6e
--- /dev/null
+++ b/chrome/browser/storage_monitor/schedule.h
@@ -0,0 +1,225 @@
+// Copyright (c) 2013 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 CHROME_BROWSER_STORAGE_MONITOR_SCHEDULE_H_
+#define CHROME_BROWSER_STORAGE_MONITOR_SCHEDULE_H_
+
+#include <map>
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/location.h"
+#include "base/memory/weak_ptr.h"
+#include "base/synchronization/lock.h"
+#include "base/task_runner.h"
+
+namespace chrome {
+
+class Schedule;
+class ScheduleImpl;
+
+// A schedule organizes the execution of a linearly staged sequence
+// of tasks. Multiple tasks can be run in parallel at each stage, a
+// stage defines a group of tasks to start together.
+// The schedule is intended to be used in a way that allows readers of the
+// code to get an overview of a particular work flow governed by the schedule.
+//
+// Stages are defined sequentially during definition of the schedule. A new
+// stage is created using the |NextStage...()| methods. The tasks comprising
+// each stage are defined using the |Run...()| methods. It is OK for a stage
+// to be empty -- it will just be skipped.
+// Tasks are intended to be defined with base::Bind closures. They can
+// be scheduled to run on a particular thread, and for tasks which launch
+// asynchronous processes, a callback can be given to them to signal completion
+// back to the schedule.
+//
+// Normal operation:
+// A schedule is a per-use object. Each time the work defined in the
+// schedule needs doing, calling code should build a new one. Calling code
+// should configure and start the schedule on a single thread. At that point,
+// task code does not need to worry about schedule thread-safety.
+// There is a convenience mechanism (OnExit()) to pass ownership of state
+// objects to the schedule which will then delete them after all stages have
+// been run or the operation is cancelled. When started, the schedule runs
+// each stage sequentially, running all tasks scheduled in each stage in
+// parallel. When all tasks have completed, the schedule advances to the next
+// stage and runs the tasks found there.
+// It is possible to conditionally execute the tasks in a stage -- if the
+// condition skips the stage, the schedule will progress to the next stage.
+// A schedule is self-deleting, and will delete itself on the thread or task
+// runner on which it was created after all tasks in the last stage have
+// completed, or if it is cancelled.
+//
+// Example:
+// scoped_ptr<SharedStateObject> flow_state(new SharedStateObject);
+// scoped_refptr<base::TaskRunner> RunnerFor(BrowserThread::ID id);
+//
+// ScheduleBuilder b("my-call-flow", FROM_HERE);
+// b.Run(base::Bind(&Task1, flow_state.get()));
+// b.NextStage();
+// b.Run(base::Bind(&Task2PartA, flow_state.get()));
+// b.Run(base::Bind(&Task2PartB));
+// b.NextStage();
+// b.RunOn(base::Bind(&Task3, flow_state.get()),
+// RunnerFor(BrowserThread::IO));
+// b.NextStage();
+// b.RunAsync(base::Bind(&AsyncWorkTask3b, flow_state.get(),
+// b.ContinueClosure()));
+// b.NextStage();
+// b.Run(base::Bind(&AllDone, flow_state.get()));
+// base::WeakPtr<Schedule> s = b.Build();
+// s->DeleteOnExit(flow_state);
+// s->Start();
+
+class ScheduleBuilder {
+ public:
+ ScheduleBuilder(const char* name, tracked_objects::Location location);
+ ~ScheduleBuilder();
+
+ // Returns a continuation closure suitable for binding to a task which starts
+ // asynchronous work. The task must run the returned closure when it has
+ // completed. When the continuation closure is invoked, the schedule will
+ // evaluate the completion status of the currently-running stage just as when
+ // any task completes.
+ // The returned closure must not be re-used: a new closure must be requested
+ // for every use.
+ // The closure may be executed on any thread.
+ base::Closure ContinueClosure();
+
+ // Returns a weak pointer to the currently-building schedule. This can be
+ // used to pass a reference to the schedule to a task. (For example, a task
+ // which may wish to cancel the schedule.)
+ base::WeakPtr<Schedule> schedule();
+
+ // Run a task within the stage the schedule is currently filling.
+ void Run(const base::Closure& task);
+
+ // Run a task on the specified |task_runner| within the
+ // stage the schedule is currently filling.
+ // (Note: to run on a MessageLoop, use MessageLoopProxy. To use a
+ // BrowserThread ID, use GetMessageLoopProxyForThread(id))
+ void RunOn(const base::Closure& task,
+ scoped_refptr<base::TaskRunner> task_runner);
+
+ // Run a task which starts asynchronous work -- the task must explicitly
+ // notify the schedule it is done using ContinueClosure().Run() before
+ // the schedule will advance.
+ void RunAsync(const base::Closure& task);
+
+ // Run a task which starts asynchronous work on the specified |task_runner|
+ // within the current stage.
+ void RunAsyncOn(const base::Closure& task,
+ scoped_refptr<base::TaskRunner> task_runner);
+
+ // Advance the currently-filling stage of the schedule. Subsequent
+ // Run... calls will fill the next stage.
+ void NextStage();
+
+ // Advance the currently-filling stage of the schedule. Makes the new stage
+ // execute conditionally. Adding a condition to a stage means the tasks
+ // registered in the stage will only execute if the condition is met when
+ // the stage would ordinarily be scheduled. The condition is checked when
+ // the stage is entered, not on schedule creation. The condition closure
+ // will be evaluated in the thread context in which the schedule was created.
+ void NextStageConditional(const base::Callback<bool(void)>& condition);
+
+ // Finalize the schedule being built and return it. After this no more
+ // modifying methods may be called on the ScheduleBuilder. The returned
+ // Schedule is not started. That should be done separately on the same thread
+ // in which it was built.
+ base::WeakPtr<Schedule> Build();
+
+ private:
+ scoped_ptr<ScheduleImpl> impl_;
+};
+
+class Schedule {
+ public:
+ // Cancel the operation of the entire schedule. A cancelled schedule will
+ // not advance to the next stage of operation regardless of other calls or
+ // preconditions being met. All currently-running tasks will be completed,
+ // but no new ones will be issued. After that, any closures registered with
+ // |OnCancel()| will be called. All OnExit closures will also be called.
+ virtual void Cancel(const tracked_objects::Location& location) = 0;
+
+ // Begins execution of the schedule's contents. Returns immediately.
+ // Must be run in the the thread context in which the schedule was built.
+ virtual void Start() = 0;
+
+ // Runs |cancel_closure| if the schedule flow is cancelled.
+ // If a |Cancel()| call is received, the schedule will not run
+ // |cancel_closure| until all running tasks in the executing stage have
+ // completed.
+ virtual void OnCancel(const base::Closure& cancel_closure) = 0;
+
+ // Runs the given |closure| after all other stages and/or cancellation
+ // closures have been run. Suitable for deleting objects used in the control
+ // flow operation, closing used resources, etc. Registered closures will run
+ // in reverse order of registration. (First registered closure will be run
+ // last.)
+ virtual void OnExit(const base::Closure& closure) = 0;
+
+ // Takes ownership of a particular object, deleting the passed state object
+ // after the schedule has terminated, whether normally or through
+ // cancellation. Registered objects will be deleted in reverse order of
+ // registration. (First registered object will be deleted last.) Deletion will
+ // happen on the creation thread of the schedule.
+ template <typename T>
+ void DeleteOnExit(T* t);
+
+ // Takes ownership of a particular type, deleting the passed state object
+ // after the schedule has terminated, whether normally or through
+ // cancellation. Registered objects will be deleted in reverse order of
+ // registration. (First registered object will be deleted last.) Deletion will
+ // happen on the creation thread of the schedule.
+ template <typename T>
+ void DeleteOnExit(scoped_ptr<T> t);
+
+ protected:
+ virtual ~Schedule();
+};
+
+// A helper function to deal with running a function with a return value.
+// This helper returns a closure that can be scheduled on any task runner which
+// runs the task which has a return value and stores the result somewhere. For
+// example, if the schedule is being used with a state object, add a T* field
+// to it and then pass that field to this function.
+// Note: you can pass the temporary storage to DeleteOnExit if you want the
+// schedule to manage the lifetime.
+template <typename T>
+base::Closure RunAndStore(const base::Callback<T(void)>& task, T* storage);
+
+namespace {
+
+template <typename T>
+void Deleter(T* t) {
+ delete t;
+}
+
+template <typename T>
+void RunAndStoreImpl(const base::Callback<T(void)>& task, T* storage) {
+ *storage = task.Run();
+}
+
+} // namespace
+
+template <typename T>
+void Schedule::DeleteOnExit(T* t) {
+ OnExit(base::Bind(&Deleter<T>, t));
+}
+
+template <typename T>
+void Schedule::DeleteOnExit(scoped_ptr<T> t) {
+ DeleteOnExit(t.release());
+}
+
+template <typename T>
+base::Closure RunAndStore(const base::Callback<T(void)>& task, T* storage) {
+ return base::Bind(&RunAndStoreImpl<T>, task, storage);
+}
+
+} // namespace chrome
+
+#endif // CHROME_BROWSER_STORAGE_MONITOR_SCHEDULE_H_

Powered by Google App Engine
This is Rietveld 408576698