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