OLD | NEW |
(Empty) | |
| 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. |
| 4 |
| 5 #include "base/bind.h" |
| 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" |
| 11 |
| 12 namespace chromeos { |
| 13 namespace file_system_provider { |
| 14 |
| 15 struct Queue::Task { |
| 16 Task() : token(0), completed(false) {} |
| 17 Task(size_t token, const AbortableCallback& callback) |
| 18 : token(token), completed(false), callback(callback) {} |
| 19 |
| 20 size_t token; |
| 21 bool completed; |
| 22 AbortableCallback callback; |
| 23 AbortCallback abort_callback; |
| 24 }; |
| 25 |
| 26 Queue::Queue(size_t max_in_parallel) |
| 27 : max_in_parallel_(max_in_parallel), |
| 28 next_token_(1), |
| 29 weak_ptr_factory_(this) { |
| 30 DCHECK_LT(0u, max_in_parallel); |
| 31 } |
| 32 |
| 33 Queue::~Queue() { |
| 34 } |
| 35 |
| 36 size_t Queue::NewToken() { |
| 37 return next_token_++; |
| 38 } |
| 39 |
| 40 AbortCallback Queue::Enqueue(size_t token, const AbortableCallback& callback) { |
| 41 #if !NDEBUG |
| 42 const auto it = executed_.find(token); |
| 43 DCHECK(it == executed_.end()); |
| 44 for (auto& task : pending_) { |
| 45 DCHECK(token != task.token); |
| 46 } |
| 47 #endif |
| 48 pending_.push_back(Task(token, callback)); |
| 49 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 50 FROM_HERE, base::Bind(&Queue::MaybeRun, weak_ptr_factory_.GetWeakPtr())); |
| 51 return base::Bind(&Queue::Abort, weak_ptr_factory_.GetWeakPtr(), token); |
| 52 } |
| 53 |
| 54 void Queue::Complete(size_t token) { |
| 55 const auto it = executed_.find(token); |
| 56 DCHECK(it != executed_.end() && !it->second.completed); |
| 57 it->second.completed = true; |
| 58 } |
| 59 |
| 60 void Queue::Remove(size_t token) { |
| 61 const auto it = executed_.find(token); |
| 62 DCHECK(it != executed_.end() && it->second.completed); |
| 63 |
| 64 executed_.erase(it); |
| 65 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 66 FROM_HERE, base::Bind(&Queue::MaybeRun, weak_ptr_factory_.GetWeakPtr())); |
| 67 } |
| 68 |
| 69 void Queue::MaybeRun() { |
| 70 if (executed_.size() == max_in_parallel_ || !pending_.size()) { |
| 71 return; |
| 72 } |
| 73 |
| 74 DCHECK_GT(max_in_parallel_, executed_.size()); |
| 75 Task task = pending_.front(); |
| 76 pending_.pop_front(); |
| 77 |
| 78 executed_[task.token] = task; |
| 79 executed_[task.token].abort_callback = task.callback.Run(); |
| 80 } |
| 81 |
| 82 void Queue::Abort(size_t token, |
| 83 const storage::AsyncFileUtil::StatusCallback& callback) { |
| 84 // Check if it's running. |
| 85 const auto it = executed_.find(token); |
| 86 if (it != executed_.end()) { |
| 87 const Task& task = it->second; |
| 88 // If the task is marked as completed, then it's impossible to abort it. |
| 89 if (task.completed) { |
| 90 callback.Run(base::File::FILE_ERROR_INVALID_OPERATION); |
| 91 return; |
| 92 } |
| 93 DCHECK(!task.abort_callback.is_null()); |
| 94 it->second.abort_callback.Run(callback); |
| 95 executed_.erase(it); |
| 96 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 97 FROM_HERE, |
| 98 base::Bind(&Queue::MaybeRun, weak_ptr_factory_.GetWeakPtr())); |
| 99 return; |
| 100 } |
| 101 |
| 102 // Aborting not running tasks is linear. TODO(mtomasz): Optimize if feasible. |
| 103 for (auto it = pending_.begin(); it != pending_.end(); ++it) { |
| 104 if (token == it->token) { |
| 105 pending_.erase(it); |
| 106 callback.Run(base::File::FILE_OK); |
| 107 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 108 FROM_HERE, |
| 109 base::Bind(&Queue::MaybeRun, weak_ptr_factory_.GetWeakPtr())); |
| 110 return; |
| 111 } |
| 112 } |
| 113 |
| 114 // The task is already removed. |
| 115 callback.Run(base::File::FILE_ERROR_INVALID_OPERATION); |
| 116 } |
| 117 |
| 118 } // namespace file_system_provider |
| 119 } // namespace chromeos |
OLD | NEW |