1 // Copyright 2015 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.
6 #include "base/location.h"
7 #include "base/logging.h"
8 #include "base/single_thread_task_runner.h"
9 #include "base/thread_task_runner_handle.h"
10 #include "chrome/browser/chromeos/file_system_provider/queue.h"
13 namespace file_system_provider
{
15 Queue::Task::Task() : token(0) {
18 Queue::Task::Task(size_t token
, const AbortableCallback
& callback
)
19 : token(token
), callback(callback
) {
22 Queue::Task::~Task() {
25 Queue::Queue(size_t max_in_parallel
)
26 : max_in_parallel_(max_in_parallel
),
28 weak_ptr_factory_(this) {
29 CHECK_LT(0u, max_in_parallel
);
35 size_t Queue::NewToken() {
39 void Queue::Enqueue(size_t token
, const AbortableCallback
& callback
) {
41 CHECK(executed_
.find(token
) == executed_
.end());
42 for (auto& task
: pending_
) {
43 CHECK(token
!= task
.token
);
46 pending_
.push_back(Task(token
, callback
));
47 base::ThreadTaskRunnerHandle::Get()->PostTask(
48 FROM_HERE
, base::Bind(&Queue::MaybeRun
, weak_ptr_factory_
.GetWeakPtr()));
51 void Queue::Complete(size_t token
) {
52 const auto it
= executed_
.find(token
);
53 CHECK(it
!= executed_
.end());
54 completed_
[token
] = it
->second
;
58 void Queue::Remove(size_t token
) {
59 const auto it
= completed_
.find(token
);
60 if (it
!= completed_
.end()) {
62 base::ThreadTaskRunnerHandle::Get()->PostTask(
64 base::Bind(&Queue::MaybeRun
, weak_ptr_factory_
.GetWeakPtr()));
68 // If not completed, then it must have been aborted.
69 const auto aborted_it
= aborted_
.find(token
);
70 CHECK(aborted_it
!= aborted_
.end());
71 aborted_
.erase(aborted_it
);
73 base::ThreadTaskRunnerHandle::Get()->PostTask(
74 FROM_HERE
, base::Bind(&Queue::MaybeRun
, weak_ptr_factory_
.GetWeakPtr()));
77 void Queue::MaybeRun() {
78 if (executed_
.size() + completed_
.size() == max_in_parallel_
||
83 CHECK_GT(max_in_parallel_
, executed_
.size() + completed_
.size());
84 Task task
= pending_
.front();
87 executed_
[task
.token
] = task
;
88 AbortCallback abort_callback
= task
.callback
.Run();
90 // It may happen that the task is completed and removed synchronously. Hence,
91 // we need to check if the task is still in the executed collection.
92 const auto executed_task_it
= executed_
.find(task
.token
);
93 if (executed_task_it
!= executed_
.end())
94 executed_task_it
->second
.abort_callback
= abort_callback
;
97 void Queue::Abort(size_t token
) {
98 // Check if it's running.
99 const auto it
= executed_
.find(token
);
100 if (it
!= executed_
.end()) {
101 Task task
= it
->second
;
102 aborted_
[token
] = task
;
104 CHECK(!task
.abort_callback
.is_null());
105 task
.abort_callback
.Run();
106 base::ThreadTaskRunnerHandle::Get()->PostTask(
108 base::Bind(&Queue::MaybeRun
, weak_ptr_factory_
.GetWeakPtr()));
112 // Aborting not running tasks is linear. TODO(mtomasz): Optimize if feasible.
113 for (auto it
= pending_
.begin(); it
!= pending_
.end(); ++it
) {
114 if (token
== it
->token
) {
115 aborted_
[token
] = *it
;
117 base::ThreadTaskRunnerHandle::Get()->PostTask(
119 base::Bind(&Queue::MaybeRun
, weak_ptr_factory_
.GetWeakPtr()));
124 // The task is already removed, marked as completed or aborted.
128 bool Queue::IsAborted(size_t token
) {
130 bool in_queue
= executed_
.find(token
) != executed_
.end() ||
131 completed_
.find(token
) != completed_
.end() ||
132 aborted_
.find(token
) != aborted_
.end();
133 for (auto& task
: pending_
) {
134 if (token
== task
.token
) {
141 return aborted_
.find(token
) != aborted_
.end();
144 } // namespace file_system_provider
145 } // namespace chromeos