1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_SYNC_TASK_MANAGER_H_
6 #define CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_SYNC_TASK_MANAGER_H_
11 #include "base/callback.h"
12 #include "base/containers/scoped_ptr_hash_map.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/memory/weak_ptr.h"
15 #include "base/sequence_checker.h"
16 #include "base/threading/sequenced_worker_pool.h"
17 #include "chrome/browser/sync_file_system/drive_backend/task_dependency_manager.h"
18 #include "chrome/browser/sync_file_system/sync_callbacks.h"
19 #include "chrome/browser/sync_file_system/sync_status_code.h"
20 #include "chrome/browser/sync_file_system/task_logger.h"
23 class SequencedTaskRunner
;
26 namespace tracked_objects
{
30 namespace sync_file_system
{
31 namespace drive_backend
{
37 // This class manages asynchronous tasks for Sync FileSystem. Each task must be
38 // either a Task or a SyncTask.
39 // The instance runs single task as the foreground task, and multiple tasks as
40 // background tasks. Running background task has a TaskBlocker that
41 // describes which task can run in parallel. When a task start running as a
42 // background task, SyncTaskManager checks if any running background task
43 // doesn't block the new background task, and queues it up if it can't run.
44 class SyncTaskManager
{
46 typedef base::Callback
<void(const SyncStatusCallback
& callback
)> Task
;
47 typedef base::Callback
<void(scoped_ptr
<SyncTaskToken
> token
)> Continuation
;
59 // Called when the manager is idle.
60 virtual void MaybeScheduleNextTask() = 0;
62 // Called when the manager is notified a task is done.
63 virtual void NotifyLastOperationStatus(
64 SyncStatusCode last_operation_status
,
65 bool last_operation_used_network
) = 0;
67 virtual void RecordTaskLog(scoped_ptr
<TaskLogger::TaskLog
> task_log
) = 0;
70 // Runs at most |maximum_background_tasks| parallel as background tasks.
71 // If |maximum_background_tasks| is zero, all task runs as foreground task.
72 SyncTaskManager(base::WeakPtr
<Client
> client
,
73 size_t maximum_background_task
,
74 const scoped_refptr
<base::SequencedTaskRunner
>& task_runner
,
75 const scoped_refptr
<base::SequencedWorkerPool
>& worker_pool
);
76 virtual ~SyncTaskManager();
78 // This needs to be called to start task scheduling.
79 // If |status| is not SYNC_STATUS_OK calling this may change the
80 // service status. This should not be called more than once.
81 void Initialize(SyncStatusCode status
);
83 // Schedules a task at the given priority.
84 void ScheduleTask(const tracked_objects::Location
& from_here
,
87 const SyncStatusCallback
& callback
);
88 void ScheduleSyncTask(const tracked_objects::Location
& from_here
,
89 scoped_ptr
<SyncTask
> task
,
91 const SyncStatusCallback
& callback
);
93 // Runs the posted task only when we're idle. Returns true if tha task is
95 bool ScheduleTaskIfIdle(const tracked_objects::Location
& from_here
,
97 const SyncStatusCallback
& callback
);
98 bool ScheduleSyncTaskIfIdle(const tracked_objects::Location
& from_here
,
99 scoped_ptr
<SyncTask
> task
,
100 const SyncStatusCallback
& callback
);
102 // Notifies SyncTaskManager that the task associated to |token| has finished
104 static void NotifyTaskDone(scoped_ptr
<SyncTaskToken
> token
,
105 SyncStatusCode status
);
107 // Updates |task_blocker| associated to the current task by specified
108 // |task_blocker| and turns the current task to a background task if
109 // the current task is running as a foreground task.
110 // If specified |task_blocker| is blocked by any other blocking factor
111 // associated to an existing background task, this function waits for the
112 // existing background task to finish.
113 // Upon the task is ready to run as a background task, calls |continuation|
114 // with new SyncTaskToken.
115 // Note that this function once releases previous |task_blocker| before
116 // applying new |task_blocker|. So, any other task may be run before
117 // invocation of |continuation|.
118 static void UpdateTaskBlocker(scoped_ptr
<SyncTaskToken
> current_task_token
,
119 scoped_ptr
<TaskBlocker
> task_blocker
,
120 const Continuation
& continuation
);
122 bool IsRunningTask(int64 task_token_id
) const;
124 void DetachFromSequence();
125 bool ShouldTrackTaskToken() const;
134 PendingTask(const base::Closure
& task
, Priority pri
, int seq
);
138 struct PendingTaskComparator
{
139 bool operator()(const PendingTask
& left
,
140 const PendingTask
& right
) const;
143 // Non-static version of NotifyTaskDone.
144 void NotifyTaskDoneBody(scoped_ptr
<SyncTaskToken
> token
,
145 SyncStatusCode status
);
147 // Non-static version of UpdateTaskBlocker.
148 void UpdateTaskBlockerBody(scoped_ptr
<SyncTaskToken
> foreground_task_token
,
149 scoped_ptr
<SyncTaskToken
> background_task_token
,
150 scoped_ptr
<TaskLogger::TaskLog
> task_log
,
151 scoped_ptr
<TaskBlocker
> task_blocker
,
152 const Continuation
& continuation
);
154 // This should be called when an async task needs to get a task token.
155 scoped_ptr
<SyncTaskToken
> GetToken(const tracked_objects::Location
& from_here
,
156 const SyncStatusCallback
& callback
);
158 scoped_ptr
<SyncTaskToken
> GetTokenForBackgroundTask(
159 const tracked_objects::Location
& from_here
,
160 const SyncStatusCallback
& callback
,
161 scoped_ptr
<TaskBlocker
> task_blocker
);
163 void PushPendingTask(const base::Closure
& closure
, Priority priority
);
165 void RunTask(scoped_ptr
<SyncTaskToken
> token
,
166 scoped_ptr
<SyncTask
> task
);
168 // Runs a pending task as a foreground task if possible.
169 // If |token| is non-nullptr, put |token| back to |token_| beforehand.
170 void MaybeStartNextForegroundTask(scoped_ptr
<SyncTaskToken
> token
);
172 base::WeakPtr
<Client
> client_
;
174 // Owns running SyncTask to cancel the task on SyncTaskManager deletion.
175 scoped_ptr
<SyncTask
> running_foreground_task_
;
177 // Owns running backgrounded SyncTask to cancel the task on SyncTaskManager
179 base::ScopedPtrHashMap
<int64
, scoped_ptr
<SyncTask
>> running_background_tasks_
;
181 size_t maximum_background_task_
;
183 // Holds pending continuation to move task to background.
184 base::Closure pending_backgrounding_task_
;
186 std::priority_queue
<PendingTask
, std::vector
<PendingTask
>,
187 PendingTaskComparator
> pending_tasks_
;
188 int64 pending_task_seq_
;
189 int64 task_token_seq_
;
191 // Absence of |token_| implies a task is running. Incoming tasks should
192 // wait for the task to finish in |pending_tasks_| if |token_| is null.
193 // Each task must take TaskToken instance from |token_| and must hold it
194 // until it finished. And the task must return the instance through
195 // NotifyTaskDone when the task finished.
196 scoped_ptr
<SyncTaskToken
> token_
;
198 TaskDependencyManager dependency_manager_
;
200 scoped_refptr
<base::SequencedTaskRunner
> task_runner_
;
201 scoped_refptr
<base::SequencedWorkerPool
> worker_pool_
;
202 base::SequenceChecker sequence_checker_
;
204 base::WeakPtrFactory
<SyncTaskManager
> weak_ptr_factory_
;;
206 DISALLOW_COPY_AND_ASSIGN(SyncTaskManager
);
209 } // namespace drive_backend
210 } // namespace sync_file_system
212 #endif // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_SYNC_TASK_MANAGER_H_