| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "net/proxy/multi_threaded_proxy_resolver.h" | 5 #include "net/proxy/multi_threaded_proxy_resolver.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
| 9 #include "base/message_loop/message_loop_proxy.h" | 9 #include "base/message_loop/message_loop_proxy.h" |
| 10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
| 11 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
| 12 #include "base/strings/stringprintf.h" | 12 #include "base/strings/stringprintf.h" |
| 13 #include "base/threading/thread.h" | 13 #include "base/threading/thread.h" |
| 14 #include "base/threading/thread_restrictions.h" | 14 #include "base/threading/thread_restrictions.h" |
| 15 #include "net/base/net_errors.h" | 15 #include "net/base/net_errors.h" |
| 16 #include "net/base/net_log.h" | 16 #include "net/base/net_log.h" |
| 17 #include "net/proxy/proxy_info.h" | 17 #include "net/proxy/proxy_info.h" |
| 18 | 18 |
| 19 // TODO(eroman): Have the MultiThreadedProxyResolver clear its PAC script | 19 // TODO(eroman): Have the MultiThreadedProxyResolver clear its PAC script |
| 20 // data when SetPacScript fails. That will reclaim memory when | 20 // data when SetPacScript fails. That will reclaim memory when |
| 21 // testing bogus scripts. | 21 // testing bogus scripts. |
| 22 | 22 |
| 23 namespace net { | 23 namespace net { |
| 24 | 24 |
| 25 // An "executor" is a job-runner for PAC requests. It encapsulates a worker | 25 // An "executor" is a job-runner for PAC requests. It encapsulates a worker |
| 26 // thread and a synchronous ProxyResolver (which will be operated on said | 26 // thread and a synchronous ProxyResolver (which will be operated on said |
| 27 // thread.) | 27 // thread.) |
| 28 class MultiThreadedProxyResolver::Executor | 28 class MultiThreadedProxyResolver::Executor |
| 29 : public base::RefCountedThreadSafe<MultiThreadedProxyResolver::Executor > { | 29 : public base::RefCountedThreadSafe<MultiThreadedProxyResolver::Executor> { |
| 30 public: | 30 public: |
| 31 // |coordinator| must remain valid throughout our lifetime. It is used to | 31 // |coordinator| must remain valid throughout our lifetime. It is used to |
| 32 // signal when the executor is ready to receive work by calling | 32 // signal when the executor is ready to receive work by calling |
| 33 // |coordinator->OnExecutorReady()|. | 33 // |coordinator->OnExecutorReady()|. |
| 34 // The constructor takes ownership of |resolver|. | 34 // The constructor takes ownership of |resolver|. |
| 35 // |thread_number| is an identifier used when naming the worker thread. | 35 // |thread_number| is an identifier used when naming the worker thread. |
| 36 Executor(MultiThreadedProxyResolver* coordinator, | 36 Executor(MultiThreadedProxyResolver* coordinator, |
| 37 ProxyResolver* resolver, | 37 ProxyResolver* resolver, |
| 38 int thread_number); | 38 int thread_number); |
| 39 | 39 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 enum Type { | 84 enum Type { |
| 85 TYPE_GET_PROXY_FOR_URL, | 85 TYPE_GET_PROXY_FOR_URL, |
| 86 TYPE_SET_PAC_SCRIPT, | 86 TYPE_SET_PAC_SCRIPT, |
| 87 TYPE_SET_PAC_SCRIPT_INTERNAL, | 87 TYPE_SET_PAC_SCRIPT_INTERNAL, |
| 88 }; | 88 }; |
| 89 | 89 |
| 90 Job(Type type, const CompletionCallback& callback) | 90 Job(Type type, const CompletionCallback& callback) |
| 91 : type_(type), | 91 : type_(type), |
| 92 callback_(callback), | 92 callback_(callback), |
| 93 executor_(NULL), | 93 executor_(NULL), |
| 94 was_cancelled_(false) { | 94 was_cancelled_(false) {} |
| 95 } | |
| 96 | 95 |
| 97 void set_executor(Executor* executor) { | 96 void set_executor(Executor* executor) { executor_ = executor; } |
| 98 executor_ = executor; | |
| 99 } | |
| 100 | 97 |
| 101 // The "executor" is the job runner that is scheduling this job. If | 98 // The "executor" is the job runner that is scheduling this job. If |
| 102 // this job has not been submitted to an executor yet, this will be | 99 // this job has not been submitted to an executor yet, this will be |
| 103 // NULL (and we know it hasn't started yet). | 100 // NULL (and we know it hasn't started yet). |
| 104 Executor* executor() { | 101 Executor* executor() { return executor_; } |
| 105 return executor_; | |
| 106 } | |
| 107 | 102 |
| 108 // Mark the job as having been cancelled. | 103 // Mark the job as having been cancelled. |
| 109 void Cancel() { | 104 void Cancel() { was_cancelled_ = true; } |
| 110 was_cancelled_ = true; | |
| 111 } | |
| 112 | 105 |
| 113 // Returns true if Cancel() has been called. | 106 // Returns true if Cancel() has been called. |
| 114 bool was_cancelled() const { return was_cancelled_; } | 107 bool was_cancelled() const { return was_cancelled_; } |
| 115 | 108 |
| 116 Type type() const { return type_; } | 109 Type type() const { return type_; } |
| 117 | 110 |
| 118 // Returns true if this job still has a user callback. Some jobs | 111 // Returns true if this job still has a user callback. Some jobs |
| 119 // do not have a user callback, because they were helper jobs | 112 // do not have a user callback, because they were helper jobs |
| 120 // scheduled internally (for example TYPE_SET_PAC_SCRIPT_INTERNAL). | 113 // scheduled internally (for example TYPE_SET_PAC_SCRIPT_INTERNAL). |
| 121 // | 114 // |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 162 }; | 155 }; |
| 163 | 156 |
| 164 // MultiThreadedProxyResolver::SetPacScriptJob --------------------------------- | 157 // MultiThreadedProxyResolver::SetPacScriptJob --------------------------------- |
| 165 | 158 |
| 166 // Runs on the worker thread to call ProxyResolver::SetPacScript. | 159 // Runs on the worker thread to call ProxyResolver::SetPacScript. |
| 167 class MultiThreadedProxyResolver::SetPacScriptJob | 160 class MultiThreadedProxyResolver::SetPacScriptJob |
| 168 : public MultiThreadedProxyResolver::Job { | 161 : public MultiThreadedProxyResolver::Job { |
| 169 public: | 162 public: |
| 170 SetPacScriptJob(const scoped_refptr<ProxyResolverScriptData>& script_data, | 163 SetPacScriptJob(const scoped_refptr<ProxyResolverScriptData>& script_data, |
| 171 const CompletionCallback& callback) | 164 const CompletionCallback& callback) |
| 172 : Job(!callback.is_null() ? TYPE_SET_PAC_SCRIPT : | 165 : Job(!callback.is_null() ? TYPE_SET_PAC_SCRIPT |
| 173 TYPE_SET_PAC_SCRIPT_INTERNAL, | 166 : TYPE_SET_PAC_SCRIPT_INTERNAL, |
| 174 callback), | 167 callback), |
| 175 script_data_(script_data) { | 168 script_data_(script_data) {} |
| 176 } | |
| 177 | 169 |
| 178 // Runs on the worker thread. | 170 // Runs on the worker thread. |
| 179 virtual void Run(scoped_refptr<base::MessageLoopProxy> origin_loop) OVERRIDE { | 171 virtual void Run(scoped_refptr<base::MessageLoopProxy> origin_loop) OVERRIDE { |
| 180 ProxyResolver* resolver = executor()->resolver(); | 172 ProxyResolver* resolver = executor()->resolver(); |
| 181 int rv = resolver->SetPacScript(script_data_, CompletionCallback()); | 173 int rv = resolver->SetPacScript(script_data_, CompletionCallback()); |
| 182 | 174 |
| 183 DCHECK_NE(rv, ERR_IO_PENDING); | 175 DCHECK_NE(rv, ERR_IO_PENDING); |
| 184 origin_loop->PostTask( | 176 origin_loop->PostTask( |
| 185 FROM_HERE, | 177 FROM_HERE, base::Bind(&SetPacScriptJob::RequestComplete, this, rv)); |
| 186 base::Bind(&SetPacScriptJob::RequestComplete, this, rv)); | |
| 187 } | 178 } |
| 188 | 179 |
| 189 protected: | 180 protected: |
| 190 virtual ~SetPacScriptJob() {} | 181 virtual ~SetPacScriptJob() {} |
| 191 | 182 |
| 192 private: | 183 private: |
| 193 // Runs the completion callback on the origin thread. | 184 // Runs the completion callback on the origin thread. |
| 194 void RequestComplete(int result_code) { | 185 void RequestComplete(int result_code) { |
| 195 // The task may have been cancelled after it was started. | 186 // The task may have been cancelled after it was started. |
| 196 if (!was_cancelled() && has_user_callback()) { | 187 if (!was_cancelled() && has_user_callback()) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 } | 235 } |
| 245 | 236 |
| 246 // Runs on the worker thread. | 237 // Runs on the worker thread. |
| 247 virtual void Run(scoped_refptr<base::MessageLoopProxy> origin_loop) OVERRIDE { | 238 virtual void Run(scoped_refptr<base::MessageLoopProxy> origin_loop) OVERRIDE { |
| 248 ProxyResolver* resolver = executor()->resolver(); | 239 ProxyResolver* resolver = executor()->resolver(); |
| 249 int rv = resolver->GetProxyForURL( | 240 int rv = resolver->GetProxyForURL( |
| 250 url_, &results_buf_, CompletionCallback(), NULL, net_log_); | 241 url_, &results_buf_, CompletionCallback(), NULL, net_log_); |
| 251 DCHECK_NE(rv, ERR_IO_PENDING); | 242 DCHECK_NE(rv, ERR_IO_PENDING); |
| 252 | 243 |
| 253 origin_loop->PostTask( | 244 origin_loop->PostTask( |
| 254 FROM_HERE, | 245 FROM_HERE, base::Bind(&GetProxyForURLJob::QueryComplete, this, rv)); |
| 255 base::Bind(&GetProxyForURLJob::QueryComplete, this, rv)); | |
| 256 } | 246 } |
| 257 | 247 |
| 258 protected: | 248 protected: |
| 259 virtual ~GetProxyForURLJob() {} | 249 virtual ~GetProxyForURLJob() {} |
| 260 | 250 |
| 261 private: | 251 private: |
| 262 // Runs the completion callback on the origin thread. | 252 // Runs the completion callback on the origin thread. |
| 263 void QueryComplete(int result_code) { | 253 void QueryComplete(int result_code) { |
| 264 // The Job may have been cancelled after it was started. | 254 // The Job may have been cancelled after it was started. |
| 265 if (!was_cancelled()) { | 255 if (!was_cancelled()) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 307 MultiThreadedProxyResolver::Executor::Executor( | 297 MultiThreadedProxyResolver::Executor::Executor( |
| 308 MultiThreadedProxyResolver* coordinator, | 298 MultiThreadedProxyResolver* coordinator, |
| 309 ProxyResolver* resolver, | 299 ProxyResolver* resolver, |
| 310 int thread_number) | 300 int thread_number) |
| 311 : coordinator_(coordinator), | 301 : coordinator_(coordinator), |
| 312 thread_number_(thread_number), | 302 thread_number_(thread_number), |
| 313 resolver_(resolver) { | 303 resolver_(resolver) { |
| 314 DCHECK(coordinator); | 304 DCHECK(coordinator); |
| 315 DCHECK(resolver); | 305 DCHECK(resolver); |
| 316 // Start up the thread. | 306 // Start up the thread. |
| 317 thread_.reset(new base::Thread(base::StringPrintf("PAC thread #%d", | 307 thread_.reset( |
| 318 thread_number))); | 308 new base::Thread(base::StringPrintf("PAC thread #%d", thread_number))); |
| 319 CHECK(thread_->Start()); | 309 CHECK(thread_->Start()); |
| 320 } | 310 } |
| 321 | 311 |
| 322 void MultiThreadedProxyResolver::Executor::StartJob(Job* job) { | 312 void MultiThreadedProxyResolver::Executor::StartJob(Job* job) { |
| 323 DCHECK(!outstanding_job_.get()); | 313 DCHECK(!outstanding_job_.get()); |
| 324 outstanding_job_ = job; | 314 outstanding_job_ = job; |
| 325 | 315 |
| 326 // Run the job. Once it has completed (regardless of whether it was | 316 // Run the job. Once it has completed (regardless of whether it was |
| 327 // cancelled), it will invoke OnJobCompleted() on this thread. | 317 // cancelled), it will invoke OnJobCompleted() on this thread. |
| 328 job->set_executor(this); | 318 job->set_executor(this); |
| 329 job->FinishedWaitingForThread(); | 319 job->FinishedWaitingForThread(); |
| 330 thread_->message_loop()->PostTask( | 320 thread_->message_loop()->PostTask( |
| 331 FROM_HERE, | 321 FROM_HERE, base::Bind(&Job::Run, job, base::MessageLoopProxy::current())); |
| 332 base::Bind(&Job::Run, job, base::MessageLoopProxy::current())); | |
| 333 } | 322 } |
| 334 | 323 |
| 335 void MultiThreadedProxyResolver::Executor::OnJobCompleted(Job* job) { | 324 void MultiThreadedProxyResolver::Executor::OnJobCompleted(Job* job) { |
| 336 DCHECK_EQ(job, outstanding_job_.get()); | 325 DCHECK_EQ(job, outstanding_job_.get()); |
| 337 outstanding_job_ = NULL; | 326 outstanding_job_ = NULL; |
| 338 coordinator_->OnExecutorReady(this); | 327 coordinator_->OnExecutorReady(this); |
| 339 } | 328 } |
| 340 | 329 |
| 341 void MultiThreadedProxyResolver::Executor::Destroy() { | 330 void MultiThreadedProxyResolver::Executor::Destroy() { |
| 342 DCHECK(coordinator_); | 331 DCHECK(coordinator_); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 DCHECK_GE(max_num_threads, 1u); | 374 DCHECK_GE(max_num_threads, 1u); |
| 386 } | 375 } |
| 387 | 376 |
| 388 MultiThreadedProxyResolver::~MultiThreadedProxyResolver() { | 377 MultiThreadedProxyResolver::~MultiThreadedProxyResolver() { |
| 389 // We will cancel all outstanding requests. | 378 // We will cancel all outstanding requests. |
| 390 pending_jobs_.clear(); | 379 pending_jobs_.clear(); |
| 391 ReleaseAllExecutors(); | 380 ReleaseAllExecutors(); |
| 392 } | 381 } |
| 393 | 382 |
| 394 int MultiThreadedProxyResolver::GetProxyForURL( | 383 int MultiThreadedProxyResolver::GetProxyForURL( |
| 395 const GURL& url, ProxyInfo* results, const CompletionCallback& callback, | 384 const GURL& url, |
| 396 RequestHandle* request, const BoundNetLog& net_log) { | 385 ProxyInfo* results, |
| 386 const CompletionCallback& callback, |
| 387 RequestHandle* request, |
| 388 const BoundNetLog& net_log) { |
| 397 DCHECK(CalledOnValidThread()); | 389 DCHECK(CalledOnValidThread()); |
| 398 DCHECK(!callback.is_null()); | 390 DCHECK(!callback.is_null()); |
| 399 DCHECK(current_script_data_.get()) | 391 DCHECK(current_script_data_.get()) |
| 400 << "Resolver is un-initialized. Must call SetPacScript() first!"; | 392 << "Resolver is un-initialized. Must call SetPacScript() first!"; |
| 401 | 393 |
| 402 scoped_refptr<GetProxyForURLJob> job( | 394 scoped_refptr<GetProxyForURLJob> job( |
| 403 new GetProxyForURLJob(url, results, callback, net_log)); | 395 new GetProxyForURLJob(url, results, callback, net_log)); |
| 404 | 396 |
| 405 // Completion will be notified through |callback|, unless the caller cancels | 397 // Completion will be notified through |callback|, unless the caller cancels |
| 406 // the request using |request|. | 398 // the request using |request|. |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 454 LoadState MultiThreadedProxyResolver::GetLoadState(RequestHandle req) const { | 446 LoadState MultiThreadedProxyResolver::GetLoadState(RequestHandle req) const { |
| 455 DCHECK(CalledOnValidThread()); | 447 DCHECK(CalledOnValidThread()); |
| 456 DCHECK(req); | 448 DCHECK(req); |
| 457 return LOAD_STATE_RESOLVING_PROXY_FOR_URL; | 449 return LOAD_STATE_RESOLVING_PROXY_FOR_URL; |
| 458 } | 450 } |
| 459 | 451 |
| 460 void MultiThreadedProxyResolver::CancelSetPacScript() { | 452 void MultiThreadedProxyResolver::CancelSetPacScript() { |
| 461 DCHECK(CalledOnValidThread()); | 453 DCHECK(CalledOnValidThread()); |
| 462 DCHECK_EQ(0u, pending_jobs_.size()); | 454 DCHECK_EQ(0u, pending_jobs_.size()); |
| 463 DCHECK_EQ(1u, executors_.size()); | 455 DCHECK_EQ(1u, executors_.size()); |
| 464 DCHECK_EQ(Job::TYPE_SET_PAC_SCRIPT, | 456 DCHECK_EQ(Job::TYPE_SET_PAC_SCRIPT, executors_[0]->outstanding_job()->type()); |
| 465 executors_[0]->outstanding_job()->type()); | |
| 466 | 457 |
| 467 // Defensively clear some data which shouldn't be getting used | 458 // Defensively clear some data which shouldn't be getting used |
| 468 // anymore. | 459 // anymore. |
| 469 current_script_data_ = NULL; | 460 current_script_data_ = NULL; |
| 470 | 461 |
| 471 ReleaseAllExecutors(); | 462 ReleaseAllExecutors(); |
| 472 } | 463 } |
| 473 | 464 |
| 474 int MultiThreadedProxyResolver::SetPacScript( | 465 int MultiThreadedProxyResolver::SetPacScript( |
| 475 const scoped_refptr<ProxyResolverScriptData>& script_data, | 466 const scoped_refptr<ProxyResolverScriptData>& script_data, |
| 476 const CompletionCallback&callback) { | 467 const CompletionCallback& callback) { |
| 477 DCHECK(CalledOnValidThread()); | 468 DCHECK(CalledOnValidThread()); |
| 478 DCHECK(!callback.is_null()); | 469 DCHECK(!callback.is_null()); |
| 479 | 470 |
| 480 // Save the script details, so we can provision new executors later. | 471 // Save the script details, so we can provision new executors later. |
| 481 current_script_data_ = script_data; | 472 current_script_data_ = script_data; |
| 482 | 473 |
| 483 // The user should not have any outstanding requests when they call | 474 // The user should not have any outstanding requests when they call |
| 484 // SetPacScript(). | 475 // SetPacScript(). |
| 485 CheckNoOutstandingUserRequests(); | 476 CheckNoOutstandingUserRequests(); |
| 486 | 477 |
| 487 // Destroy all of the current threads and their proxy resolvers. | 478 // Destroy all of the current threads and their proxy resolvers. |
| 488 ReleaseAllExecutors(); | 479 ReleaseAllExecutors(); |
| 489 | 480 |
| 490 // Provision a new executor, and run the SetPacScript request. On completion | 481 // Provision a new executor, and run the SetPacScript request. On completion |
| 491 // notification will be sent through |callback|. | 482 // notification will be sent through |callback|. |
| 492 Executor* executor = AddNewExecutor(); | 483 Executor* executor = AddNewExecutor(); |
| 493 executor->StartJob(new SetPacScriptJob(script_data, callback)); | 484 executor->StartJob(new SetPacScriptJob(script_data, callback)); |
| 494 return ERR_IO_PENDING; | 485 return ERR_IO_PENDING; |
| 495 } | 486 } |
| 496 | 487 |
| 497 void MultiThreadedProxyResolver::CheckNoOutstandingUserRequests() const { | 488 void MultiThreadedProxyResolver::CheckNoOutstandingUserRequests() const { |
| 498 DCHECK(CalledOnValidThread()); | 489 DCHECK(CalledOnValidThread()); |
| 499 CHECK_EQ(0u, pending_jobs_.size()); | 490 CHECK_EQ(0u, pending_jobs_.size()); |
| 500 | 491 |
| 501 for (ExecutorList::const_iterator it = executors_.begin(); | 492 for (ExecutorList::const_iterator it = executors_.begin(); |
| 502 it != executors_.end(); ++it) { | 493 it != executors_.end(); |
| 494 ++it) { |
| 503 const Executor* executor = it->get(); | 495 const Executor* executor = it->get(); |
| 504 Job* job = executor->outstanding_job(); | 496 Job* job = executor->outstanding_job(); |
| 505 // The "has_user_callback()" is to exclude jobs for which the callback | 497 // The "has_user_callback()" is to exclude jobs for which the callback |
| 506 // has already been invoked, or was not user-initiated (as in the case of | 498 // has already been invoked, or was not user-initiated (as in the case of |
| 507 // lazy thread provisions). User-initiated jobs may !has_user_callback() | 499 // lazy thread provisions). User-initiated jobs may !has_user_callback() |
| 508 // when the callback has already been run. (Since we only clear the | 500 // when the callback has already been run. (Since we only clear the |
| 509 // outstanding job AFTER the callback has been invoked, it is possible | 501 // outstanding job AFTER the callback has been invoked, it is possible |
| 510 // for a new request to be started from within the callback). | 502 // for a new request to be started from within the callback). |
| 511 CHECK(!job || job->was_cancelled() || !job->has_user_callback()); | 503 CHECK(!job || job->was_cancelled() || !job->has_user_callback()); |
| 512 } | 504 } |
| 513 } | 505 } |
| 514 | 506 |
| 515 void MultiThreadedProxyResolver::ReleaseAllExecutors() { | 507 void MultiThreadedProxyResolver::ReleaseAllExecutors() { |
| 516 DCHECK(CalledOnValidThread()); | 508 DCHECK(CalledOnValidThread()); |
| 517 for (ExecutorList::iterator it = executors_.begin(); | 509 for (ExecutorList::iterator it = executors_.begin(); it != executors_.end(); |
| 518 it != executors_.end(); ++it) { | 510 ++it) { |
| 519 Executor* executor = it->get(); | 511 Executor* executor = it->get(); |
| 520 executor->Destroy(); | 512 executor->Destroy(); |
| 521 } | 513 } |
| 522 executors_.clear(); | 514 executors_.clear(); |
| 523 } | 515 } |
| 524 | 516 |
| 525 MultiThreadedProxyResolver::Executor* | 517 MultiThreadedProxyResolver::Executor* |
| 526 MultiThreadedProxyResolver::FindIdleExecutor() { | 518 MultiThreadedProxyResolver::FindIdleExecutor() { |
| 527 DCHECK(CalledOnValidThread()); | 519 DCHECK(CalledOnValidThread()); |
| 528 for (ExecutorList::iterator it = executors_.begin(); | 520 for (ExecutorList::iterator it = executors_.begin(); it != executors_.end(); |
| 529 it != executors_.end(); ++it) { | 521 ++it) { |
| 530 Executor* executor = it->get(); | 522 Executor* executor = it->get(); |
| 531 if (!executor->outstanding_job()) | 523 if (!executor->outstanding_job()) |
| 532 return executor; | 524 return executor; |
| 533 } | 525 } |
| 534 return NULL; | 526 return NULL; |
| 535 } | 527 } |
| 536 | 528 |
| 537 MultiThreadedProxyResolver::Executor* | 529 MultiThreadedProxyResolver::Executor* |
| 538 MultiThreadedProxyResolver::AddNewExecutor() { | 530 MultiThreadedProxyResolver::AddNewExecutor() { |
| 539 DCHECK(CalledOnValidThread()); | 531 DCHECK(CalledOnValidThread()); |
| 540 DCHECK_LT(executors_.size(), max_num_threads_); | 532 DCHECK_LT(executors_.size(), max_num_threads_); |
| 541 // The "thread number" is used to give the thread a unique name. | 533 // The "thread number" is used to give the thread a unique name. |
| 542 int thread_number = executors_.size(); | 534 int thread_number = executors_.size(); |
| 543 ProxyResolver* resolver = resolver_factory_->CreateProxyResolver(); | 535 ProxyResolver* resolver = resolver_factory_->CreateProxyResolver(); |
| 544 Executor* executor = new Executor( | 536 Executor* executor = new Executor(this, resolver, thread_number); |
| 545 this, resolver, thread_number); | |
| 546 executors_.push_back(make_scoped_refptr(executor)); | 537 executors_.push_back(make_scoped_refptr(executor)); |
| 547 return executor; | 538 return executor; |
| 548 } | 539 } |
| 549 | 540 |
| 550 void MultiThreadedProxyResolver::OnExecutorReady(Executor* executor) { | 541 void MultiThreadedProxyResolver::OnExecutorReady(Executor* executor) { |
| 551 DCHECK(CalledOnValidThread()); | 542 DCHECK(CalledOnValidThread()); |
| 552 if (pending_jobs_.empty()) | 543 if (pending_jobs_.empty()) |
| 553 return; | 544 return; |
| 554 | 545 |
| 555 // Get the next job to process (FIFO). Transfer it from the pending queue | 546 // Get the next job to process (FIFO). Transfer it from the pending queue |
| 556 // to the executor. | 547 // to the executor. |
| 557 scoped_refptr<Job> job = pending_jobs_.front(); | 548 scoped_refptr<Job> job = pending_jobs_.front(); |
| 558 pending_jobs_.pop_front(); | 549 pending_jobs_.pop_front(); |
| 559 executor->StartJob(job.get()); | 550 executor->StartJob(job.get()); |
| 560 } | 551 } |
| 561 | 552 |
| 562 } // namespace net | 553 } // namespace net |
| OLD | NEW |