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

Side by Side Diff: components/update_client/update_client.cc

Issue 1419473005: Fix task concurrency in components/update_client (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 1 month 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 unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/update_client/update_client.h" 5 #include "components/update_client/update_client.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <queue> 8 #include <queue>
9 #include <set> 9 #include <set>
10 #include <utility> 10 #include <utility>
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 UpdateClientImpl::~UpdateClientImpl() { 82 UpdateClientImpl::~UpdateClientImpl() {
83 DCHECK(thread_checker_.CalledOnValidThread()); 83 DCHECK(thread_checker_.CalledOnValidThread());
84 config_ = nullptr; 84 config_ = nullptr;
85 } 85 }
86 86
87 void UpdateClientImpl::Install(const std::string& id, 87 void UpdateClientImpl::Install(const std::string& id,
88 const CrxDataCallback& crx_data_callback, 88 const CrxDataCallback& crx_data_callback,
89 const CompletionCallback& completion_callback) { 89 const CompletionCallback& completion_callback) {
90 DCHECK(thread_checker_.CalledOnValidThread()); 90 DCHECK(thread_checker_.CalledOnValidThread());
91 91
92 if (update_engine_->IsUpdating(id)) { 92 if (IsUpdating(id)) {
93 completion_callback.Run(Error::ERROR_UPDATE_IN_PROGRESS); 93 completion_callback.Run(Error::ERROR_UPDATE_IN_PROGRESS);
94 return; 94 return;
95 } 95 }
96 96
97 std::vector<std::string> ids; 97 std::vector<std::string> ids;
98 ids.push_back(id); 98 ids.push_back(id);
99 99
100 // Partially applies |completion_callback| to OnTaskComplete, so this 100 // Partially applies |completion_callback| to OnTaskComplete, so this
101 // argument is available when the task completes, along with the task itself. 101 // argument is available when the task completes, along with the task itself.
102 const auto callback = 102 const auto callback =
103 base::Bind(&UpdateClientImpl::OnTaskComplete, this, completion_callback); 103 base::Bind(&UpdateClientImpl::OnTaskComplete, this, completion_callback);
104 scoped_ptr<TaskUpdate> task(new TaskUpdate(update_engine_.get(), true, ids, 104 scoped_ptr<TaskUpdate> task(new TaskUpdate(update_engine_.get(), true, ids,
105 crx_data_callback, callback)); 105 crx_data_callback, callback));
106 106
107 // Install tasks are run concurrently and never queued up.
107 auto it = tasks_.insert(task.release()).first; 108 auto it = tasks_.insert(task.release()).first;
108 RunTask(*it); 109 RunTask(*it);
109 } 110 }
110 111
111 void UpdateClientImpl::Update(const std::vector<std::string>& ids, 112 void UpdateClientImpl::Update(const std::vector<std::string>& ids,
112 const CrxDataCallback& crx_data_callback, 113 const CrxDataCallback& crx_data_callback,
113 const CompletionCallback& completion_callback) { 114 const CompletionCallback& completion_callback) {
114 DCHECK(thread_checker_.CalledOnValidThread()); 115 DCHECK(thread_checker_.CalledOnValidThread());
115 116
116 const auto callback = 117 const auto callback =
117 base::Bind(&UpdateClientImpl::OnTaskComplete, this, completion_callback); 118 base::Bind(&UpdateClientImpl::OnTaskComplete, this, completion_callback);
118 scoped_ptr<TaskUpdate> task(new TaskUpdate(update_engine_.get(), false, ids, 119 scoped_ptr<TaskUpdate> task(new TaskUpdate(update_engine_.get(), false, ids,
119 crx_data_callback, callback)); 120 crx_data_callback, callback));
120 121
122 // If no other tasks are running at the moment, run this update task.
123 // Otherwise, queue the task up.
121 if (tasks_.empty()) { 124 if (tasks_.empty()) {
122 auto it = tasks_.insert(task.release()).first; 125 auto it = tasks_.insert(task.release()).first;
123 RunTask(*it); 126 RunTask(*it);
124 } else { 127 } else {
125 task_queue_.push(task.release()); 128 task_queue_.push(task.release());
126 } 129 }
127 } 130 }
128 131
129 void UpdateClientImpl::RunTask(Task* task) { 132 void UpdateClientImpl::RunTask(Task* task) {
130 DCHECK(thread_checker_.CalledOnValidThread()); 133 DCHECK(thread_checker_.CalledOnValidThread());
131 base::ThreadTaskRunnerHandle::Get()->PostTask( 134 base::ThreadTaskRunnerHandle::Get()->PostTask(
132 FROM_HERE, base::Bind(&Task::Run, base::Unretained(task))); 135 FROM_HERE, base::Bind(&Task::Run, base::Unretained(task)));
133 } 136 }
134 137
135 void UpdateClientImpl::OnTaskComplete( 138 void UpdateClientImpl::OnTaskComplete(
136 const CompletionCallback& completion_callback, 139 const CompletionCallback& completion_callback,
137 Task* task, 140 Task* task,
138 int error) { 141 int error) {
139 DCHECK(thread_checker_.CalledOnValidThread()); 142 DCHECK(thread_checker_.CalledOnValidThread());
140 DCHECK(task); 143 DCHECK(task);
141 144
142 base::ThreadTaskRunnerHandle::Get()->PostTask( 145 base::ThreadTaskRunnerHandle::Get()->PostTask(
143 FROM_HERE, base::Bind(completion_callback, error)); 146 FROM_HERE, base::Bind(completion_callback, error));
144 147
145 tasks_.erase(task); 148 tasks_.erase(task);
146 delete task; 149 delete task;
147 150
148 if (!task_queue_.empty()) { 151 // Pick up a task from the queue if the queue has pending tasks and no other
152 // task is running.
153 if (tasks_.empty() && !task_queue_.empty()) {
149 RunTask(task_queue_.front()); 154 RunTask(task_queue_.front());
150 task_queue_.pop(); 155 task_queue_.pop();
151 } 156 }
152 } 157 }
153 158
154 void UpdateClientImpl::AddObserver(Observer* observer) { 159 void UpdateClientImpl::AddObserver(Observer* observer) {
155 DCHECK(thread_checker_.CalledOnValidThread()); 160 DCHECK(thread_checker_.CalledOnValidThread());
156 observer_list_.AddObserver(observer); 161 observer_list_.AddObserver(observer);
157 } 162 }
158 163
159 void UpdateClientImpl::RemoveObserver(Observer* observer) { 164 void UpdateClientImpl::RemoveObserver(Observer* observer) {
160 DCHECK(thread_checker_.CalledOnValidThread()); 165 DCHECK(thread_checker_.CalledOnValidThread());
161 observer_list_.RemoveObserver(observer); 166 observer_list_.RemoveObserver(observer);
162 } 167 }
163 168
164 void UpdateClientImpl::NotifyObservers(Observer::Events event, 169 void UpdateClientImpl::NotifyObservers(Observer::Events event,
165 const std::string& id) { 170 const std::string& id) {
166 DCHECK(thread_checker_.CalledOnValidThread()); 171 DCHECK(thread_checker_.CalledOnValidThread());
167 FOR_EACH_OBSERVER(Observer, observer_list_, OnEvent(event, id)); 172 FOR_EACH_OBSERVER(Observer, observer_list_, OnEvent(event, id));
168 } 173 }
169 174
170 bool UpdateClientImpl::GetCrxUpdateState(const std::string& id, 175 bool UpdateClientImpl::GetCrxUpdateState(const std::string& id,
171 CrxUpdateItem* update_item) const { 176 CrxUpdateItem* update_item) const {
172 return update_engine_->GetUpdateState(id, update_item); 177 return update_engine_->GetUpdateState(id, update_item);
173 } 178 }
174 179
175 bool UpdateClientImpl::IsUpdating(const std::string& id) const { 180 bool UpdateClientImpl::IsUpdating(const std::string& id) const {
176 return update_engine_->IsUpdating(id); 181 DCHECK(thread_checker_.CalledOnValidThread());
182
183 for (const auto& task : tasks_) {
184 const auto ids(task->GetIds());
185 if (std::find(std::begin(ids), std::end(ids), id) != std::end(ids)) {
186 return true;
187 }
188 }
189
190 return false;
177 } 191 }
178 192
179 scoped_refptr<UpdateClient> UpdateClientFactory( 193 scoped_refptr<UpdateClient> UpdateClientFactory(
180 const scoped_refptr<Configurator>& config) { 194 const scoped_refptr<Configurator>& config) {
181 scoped_ptr<PingManager> ping_manager(new PingManager(*config)); 195 scoped_ptr<PingManager> ping_manager(new PingManager(*config));
182 return new UpdateClientImpl(config, ping_manager.Pass(), 196 return new UpdateClientImpl(config, ping_manager.Pass(),
183 &UpdateChecker::Create, &CrxDownloader::Create); 197 &UpdateChecker::Create, &CrxDownloader::Create);
184 } 198 }
185 199
186 } // namespace update_client 200 } // namespace update_client
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698