| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/message_loop_proxy.h" | 8 #include "base/message_loop_proxy.h" |
| 8 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 9 #include "base/stringprintf.h" | 10 #include "base/stringprintf.h" |
| 10 #include "base/threading/thread.h" | 11 #include "base/threading/thread.h" |
| 11 #include "base/threading/thread_restrictions.h" | 12 #include "base/threading/thread_restrictions.h" |
| 12 #include "net/base/net_errors.h" | 13 #include "net/base/net_errors.h" |
| 13 #include "net/base/net_log.h" | 14 #include "net/base/net_log.h" |
| 14 #include "net/proxy/proxy_info.h" | 15 #include "net/proxy/proxy_info.h" |
| 15 | 16 |
| 16 // TODO(eroman): Have the MultiThreadedProxyResolver clear its PAC script | 17 // TODO(eroman): Have the MultiThreadedProxyResolver clear its PAC script |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 class MultiThreadedProxyResolver::Job | 94 class MultiThreadedProxyResolver::Job |
| 94 : public base::RefCountedThreadSafe<MultiThreadedProxyResolver::Job> { | 95 : public base::RefCountedThreadSafe<MultiThreadedProxyResolver::Job> { |
| 95 public: | 96 public: |
| 96 // Identifies the subclass of Job (only being used for debugging purposes). | 97 // Identifies the subclass of Job (only being used for debugging purposes). |
| 97 enum Type { | 98 enum Type { |
| 98 TYPE_GET_PROXY_FOR_URL, | 99 TYPE_GET_PROXY_FOR_URL, |
| 99 TYPE_SET_PAC_SCRIPT, | 100 TYPE_SET_PAC_SCRIPT, |
| 100 TYPE_SET_PAC_SCRIPT_INTERNAL, | 101 TYPE_SET_PAC_SCRIPT_INTERNAL, |
| 101 }; | 102 }; |
| 102 | 103 |
| 103 Job(Type type, OldCompletionCallback* user_callback) | 104 Job(Type type, const CompletionCallback& callback) |
| 104 : type_(type), | 105 : type_(type), |
| 105 user_callback_(user_callback), | 106 callback_(callback), |
| 106 executor_(NULL), | 107 executor_(NULL), |
| 107 was_cancelled_(false) { | 108 was_cancelled_(false) { |
| 108 } | 109 } |
| 109 | 110 |
| 110 void set_executor(Executor* executor) { | 111 void set_executor(Executor* executor) { |
| 111 executor_ = executor; | 112 executor_ = executor; |
| 112 } | 113 } |
| 113 | 114 |
| 114 // The "executor" is the job runner that is scheduling this job. If | 115 // The "executor" is the job runner that is scheduling this job. If |
| 115 // this job has not been submitted to an executor yet, this will be | 116 // this job has not been submitted to an executor yet, this will be |
| (...skipping 10 matching lines...) Expand all Loading... |
| 126 // Returns true if Cancel() has been called. | 127 // Returns true if Cancel() has been called. |
| 127 bool was_cancelled() const { return was_cancelled_; } | 128 bool was_cancelled() const { return was_cancelled_; } |
| 128 | 129 |
| 129 Type type() const { return type_; } | 130 Type type() const { return type_; } |
| 130 | 131 |
| 131 // Returns true if this job still has a user callback. Some jobs | 132 // Returns true if this job still has a user callback. Some jobs |
| 132 // do not have a user callback, because they were helper jobs | 133 // do not have a user callback, because they were helper jobs |
| 133 // scheduled internally (for example TYPE_SET_PAC_SCRIPT_INTERNAL). | 134 // scheduled internally (for example TYPE_SET_PAC_SCRIPT_INTERNAL). |
| 134 // | 135 // |
| 135 // Otherwise jobs that correspond with user-initiated work will | 136 // Otherwise jobs that correspond with user-initiated work will |
| 136 // have a non-NULL callback up until the callback is run. | 137 // have a non-null callback up until the callback is run. |
| 137 bool has_user_callback() const { return user_callback_ != NULL; } | 138 bool has_user_callback() const { return !callback_.is_null(); } |
| 138 | 139 |
| 139 // This method is called when the job is inserted into a wait queue | 140 // This method is called when the job is inserted into a wait queue |
| 140 // because no executors were ready to accept it. | 141 // because no executors were ready to accept it. |
| 141 virtual void WaitingForThread() {} | 142 virtual void WaitingForThread() {} |
| 142 | 143 |
| 143 // This method is called just before the job is posted to the work thread. | 144 // This method is called just before the job is posted to the work thread. |
| 144 virtual void FinishedWaitingForThread() {} | 145 virtual void FinishedWaitingForThread() {} |
| 145 | 146 |
| 146 // This method is called on the worker thread to do the job's work. On | 147 // This method is called on the worker thread to do the job's work. On |
| 147 // completion, implementors are expected to call OnJobCompleted() on | 148 // completion, implementors are expected to call OnJobCompleted() on |
| 148 // |origin_loop|. | 149 // |origin_loop|. |
| 149 virtual void Run(scoped_refptr<base::MessageLoopProxy> origin_loop) = 0; | 150 virtual void Run(scoped_refptr<base::MessageLoopProxy> origin_loop) = 0; |
| 150 | 151 |
| 151 protected: | 152 protected: |
| 152 void OnJobCompleted() { | 153 void OnJobCompleted() { |
| 153 // |executor_| will be NULL if the executor has already been deleted. | 154 // |executor_| will be NULL if the executor has already been deleted. |
| 154 if (executor_) | 155 if (executor_) |
| 155 executor_->OnJobCompleted(this); | 156 executor_->OnJobCompleted(this); |
| 156 } | 157 } |
| 157 | 158 |
| 158 void RunUserCallback(int result) { | 159 void RunUserCallback(int result) { |
| 159 DCHECK(has_user_callback()); | 160 DCHECK(has_user_callback()); |
| 160 OldCompletionCallback* callback = user_callback_; | 161 CompletionCallback callback = callback_; |
| 161 // Null the callback so has_user_callback() will now return false. | 162 // Reset the callback so has_user_callback() will now return false. |
| 162 user_callback_ = NULL; | 163 callback_.Reset(); |
| 163 callback->Run(result); | 164 callback.Run(result); |
| 164 } | 165 } |
| 165 | 166 |
| 166 friend class base::RefCountedThreadSafe<MultiThreadedProxyResolver::Job>; | 167 friend class base::RefCountedThreadSafe<MultiThreadedProxyResolver::Job>; |
| 167 | 168 |
| 168 virtual ~Job() {} | 169 virtual ~Job() {} |
| 169 | 170 |
| 170 private: | 171 private: |
| 171 const Type type_; | 172 const Type type_; |
| 172 OldCompletionCallback* user_callback_; | 173 CompletionCallback callback_; |
| 173 Executor* executor_; | 174 Executor* executor_; |
| 174 bool was_cancelled_; | 175 bool was_cancelled_; |
| 175 }; | 176 }; |
| 176 | 177 |
| 177 // MultiThreadedProxyResolver::SetPacScriptJob --------------------------------- | 178 // MultiThreadedProxyResolver::SetPacScriptJob --------------------------------- |
| 178 | 179 |
| 179 // Runs on the worker thread to call ProxyResolver::SetPacScript. | 180 // Runs on the worker thread to call ProxyResolver::SetPacScript. |
| 180 class MultiThreadedProxyResolver::SetPacScriptJob | 181 class MultiThreadedProxyResolver::SetPacScriptJob |
| 181 : public MultiThreadedProxyResolver::Job { | 182 : public MultiThreadedProxyResolver::Job { |
| 182 public: | 183 public: |
| 183 SetPacScriptJob(const scoped_refptr<ProxyResolverScriptData>& script_data, | 184 SetPacScriptJob(const scoped_refptr<ProxyResolverScriptData>& script_data, |
| 184 OldCompletionCallback* callback) | 185 const CompletionCallback& callback) |
| 185 : Job(callback ? TYPE_SET_PAC_SCRIPT : TYPE_SET_PAC_SCRIPT_INTERNAL, | 186 : Job(!callback.is_null() ? TYPE_SET_PAC_SCRIPT : |
| 187 TYPE_SET_PAC_SCRIPT_INTERNAL, |
| 186 callback), | 188 callback), |
| 187 script_data_(script_data) { | 189 script_data_(script_data) { |
| 188 } | 190 } |
| 189 | 191 |
| 190 // Runs on the worker thread. | 192 // Runs on the worker thread. |
| 191 virtual void Run(scoped_refptr<base::MessageLoopProxy> origin_loop) OVERRIDE { | 193 virtual void Run(scoped_refptr<base::MessageLoopProxy> origin_loop) OVERRIDE { |
| 192 ProxyResolver* resolver = executor()->resolver(); | 194 ProxyResolver* resolver = executor()->resolver(); |
| 193 int rv = resolver->SetPacScript(script_data_, NULL); | 195 int rv = resolver->SetPacScript(script_data_, CompletionCallback()); |
| 194 | 196 |
| 195 DCHECK_NE(rv, ERR_IO_PENDING); | 197 DCHECK_NE(rv, ERR_IO_PENDING); |
| 196 origin_loop->PostTask( | 198 origin_loop->PostTask( |
| 197 FROM_HERE, | 199 FROM_HERE, |
| 198 NewRunnableMethod(this, &SetPacScriptJob::RequestComplete, rv)); | 200 base::Bind(&SetPacScriptJob::RequestComplete, this, rv)); |
| 199 } | 201 } |
| 200 | 202 |
| 201 private: | 203 private: |
| 202 // Runs the completion callback on the origin thread. | 204 // Runs the completion callback on the origin thread. |
| 203 void RequestComplete(int result_code) { | 205 void RequestComplete(int result_code) { |
| 204 // The task may have been cancelled after it was started. | 206 // The task may have been cancelled after it was started. |
| 205 if (!was_cancelled() && has_user_callback()) { | 207 if (!was_cancelled() && has_user_callback()) { |
| 206 RunUserCallback(result_code); | 208 RunUserCallback(result_code); |
| 207 } | 209 } |
| 208 OnJobCompleted(); | 210 OnJobCompleted(); |
| 209 } | 211 } |
| 210 | 212 |
| 211 const scoped_refptr<ProxyResolverScriptData> script_data_; | 213 const scoped_refptr<ProxyResolverScriptData> script_data_; |
| 212 }; | 214 }; |
| 213 | 215 |
| 214 // MultiThreadedProxyResolver::GetProxyForURLJob ------------------------------ | 216 // MultiThreadedProxyResolver::GetProxyForURLJob ------------------------------ |
| 215 | 217 |
| 216 class MultiThreadedProxyResolver::GetProxyForURLJob | 218 class MultiThreadedProxyResolver::GetProxyForURLJob |
| 217 : public MultiThreadedProxyResolver::Job { | 219 : public MultiThreadedProxyResolver::Job { |
| 218 public: | 220 public: |
| 219 // |url| -- the URL of the query. | 221 // |url| -- the URL of the query. |
| 220 // |results| -- the structure to fill with proxy resolve results. | 222 // |results| -- the structure to fill with proxy resolve results. |
| 221 GetProxyForURLJob(const GURL& url, | 223 GetProxyForURLJob(const GURL& url, |
| 222 ProxyInfo* results, | 224 ProxyInfo* results, |
| 223 OldCompletionCallback* callback, | 225 const CompletionCallback& callback, |
| 224 const BoundNetLog& net_log) | 226 const BoundNetLog& net_log) |
| 225 : Job(TYPE_GET_PROXY_FOR_URL, callback), | 227 : Job(TYPE_GET_PROXY_FOR_URL, callback), |
| 226 results_(results), | 228 results_(results), |
| 227 net_log_(net_log), | 229 net_log_(net_log), |
| 228 url_(url), | 230 url_(url), |
| 229 was_waiting_for_thread_(false) { | 231 was_waiting_for_thread_(false) { |
| 230 DCHECK(callback); | 232 DCHECK(!callback.is_null()); |
| 231 } | 233 } |
| 232 | 234 |
| 233 BoundNetLog* net_log() { return &net_log_; } | 235 BoundNetLog* net_log() { return &net_log_; } |
| 234 | 236 |
| 235 virtual void WaitingForThread() OVERRIDE { | 237 virtual void WaitingForThread() OVERRIDE { |
| 236 was_waiting_for_thread_ = true; | 238 was_waiting_for_thread_ = true; |
| 237 net_log_.BeginEvent( | 239 net_log_.BeginEvent( |
| 238 NetLog::TYPE_WAITING_FOR_PROXY_RESOLVER_THREAD, NULL); | 240 NetLog::TYPE_WAITING_FOR_PROXY_RESOLVER_THREAD, NULL); |
| 239 } | 241 } |
| 240 | 242 |
| 241 virtual void FinishedWaitingForThread() OVERRIDE { | 243 virtual void FinishedWaitingForThread() OVERRIDE { |
| 242 DCHECK(executor()); | 244 DCHECK(executor()); |
| 243 | 245 |
| 244 if (was_waiting_for_thread_) { | 246 if (was_waiting_for_thread_) { |
| 245 net_log_.EndEvent( | 247 net_log_.EndEvent( |
| 246 NetLog::TYPE_WAITING_FOR_PROXY_RESOLVER_THREAD, NULL); | 248 NetLog::TYPE_WAITING_FOR_PROXY_RESOLVER_THREAD, NULL); |
| 247 } | 249 } |
| 248 | 250 |
| 249 net_log_.AddEvent( | 251 net_log_.AddEvent( |
| 250 NetLog::TYPE_SUBMITTED_TO_RESOLVER_THREAD, | 252 NetLog::TYPE_SUBMITTED_TO_RESOLVER_THREAD, |
| 251 make_scoped_refptr(new NetLogIntegerParameter( | 253 make_scoped_refptr(new NetLogIntegerParameter( |
| 252 "thread_number", executor()->thread_number()))); | 254 "thread_number", executor()->thread_number()))); |
| 253 } | 255 } |
| 254 | 256 |
| 255 // Runs on the worker thread. | 257 // Runs on the worker thread. |
| 256 virtual void Run(scoped_refptr<base::MessageLoopProxy> origin_loop) OVERRIDE { | 258 virtual void Run(scoped_refptr<base::MessageLoopProxy> origin_loop) OVERRIDE { |
| 257 ProxyResolver* resolver = executor()->resolver(); | 259 ProxyResolver* resolver = executor()->resolver(); |
| 258 int rv = resolver->GetProxyForURL( | 260 int rv = resolver->GetProxyForURL( |
| 259 url_, &results_buf_, NULL, NULL, net_log_); | 261 url_, &results_buf_, CompletionCallback(), NULL, net_log_); |
| 260 DCHECK_NE(rv, ERR_IO_PENDING); | 262 DCHECK_NE(rv, ERR_IO_PENDING); |
| 261 | 263 |
| 262 origin_loop->PostTask( | 264 origin_loop->PostTask( |
| 263 FROM_HERE, | 265 FROM_HERE, |
| 264 NewRunnableMethod(this, &GetProxyForURLJob::QueryComplete, rv)); | 266 base::Bind(&GetProxyForURLJob::QueryComplete, this, rv)); |
| 265 } | 267 } |
| 266 | 268 |
| 267 private: | 269 private: |
| 268 // Runs the completion callback on the origin thread. | 270 // Runs the completion callback on the origin thread. |
| 269 void QueryComplete(int result_code) { | 271 void QueryComplete(int result_code) { |
| 270 // The Job may have been cancelled after it was started. | 272 // The Job may have been cancelled after it was started. |
| 271 if (!was_cancelled()) { | 273 if (!was_cancelled()) { |
| 272 if (result_code >= OK) { // Note: unit-tests use values > 0. | 274 if (result_code >= OK) { // Note: unit-tests use values > 0. |
| 273 results_->Use(results_buf_); | 275 results_->Use(results_buf_); |
| 274 } | 276 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 void MultiThreadedProxyResolver::Executor::StartJob(Job* job) { | 315 void MultiThreadedProxyResolver::Executor::StartJob(Job* job) { |
| 314 DCHECK(!outstanding_job_); | 316 DCHECK(!outstanding_job_); |
| 315 outstanding_job_ = job; | 317 outstanding_job_ = job; |
| 316 | 318 |
| 317 // Run the job. Once it has completed (regardless of whether it was | 319 // Run the job. Once it has completed (regardless of whether it was |
| 318 // cancelled), it will invoke OnJobCompleted() on this thread. | 320 // cancelled), it will invoke OnJobCompleted() on this thread. |
| 319 job->set_executor(this); | 321 job->set_executor(this); |
| 320 job->FinishedWaitingForThread(); | 322 job->FinishedWaitingForThread(); |
| 321 thread_->message_loop()->PostTask( | 323 thread_->message_loop()->PostTask( |
| 322 FROM_HERE, | 324 FROM_HERE, |
| 323 NewRunnableMethod(job, &Job::Run, | 325 base::Bind(&Job::Run, job, base::MessageLoopProxy::current())); |
| 324 base::MessageLoopProxy::current())); | |
| 325 } | 326 } |
| 326 | 327 |
| 327 void MultiThreadedProxyResolver::Executor::OnJobCompleted(Job* job) { | 328 void MultiThreadedProxyResolver::Executor::OnJobCompleted(Job* job) { |
| 328 DCHECK_EQ(job, outstanding_job_.get()); | 329 DCHECK_EQ(job, outstanding_job_.get()); |
| 329 outstanding_job_ = NULL; | 330 outstanding_job_ = NULL; |
| 330 coordinator_->OnExecutorReady(this); | 331 coordinator_->OnExecutorReady(this); |
| 331 } | 332 } |
| 332 | 333 |
| 333 void MultiThreadedProxyResolver::Executor::Destroy() { | 334 void MultiThreadedProxyResolver::Executor::Destroy() { |
| 334 DCHECK(coordinator_); | 335 DCHECK(coordinator_); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 359 | 360 |
| 360 // Null some stuff as a precaution. | 361 // Null some stuff as a precaution. |
| 361 coordinator_ = NULL; | 362 coordinator_ = NULL; |
| 362 outstanding_job_ = NULL; | 363 outstanding_job_ = NULL; |
| 363 } | 364 } |
| 364 | 365 |
| 365 void MultiThreadedProxyResolver::Executor::PurgeMemory() { | 366 void MultiThreadedProxyResolver::Executor::PurgeMemory() { |
| 366 scoped_refptr<PurgeMemoryTask> helper(new PurgeMemoryTask(resolver_.get())); | 367 scoped_refptr<PurgeMemoryTask> helper(new PurgeMemoryTask(resolver_.get())); |
| 367 thread_->message_loop()->PostTask( | 368 thread_->message_loop()->PostTask( |
| 368 FROM_HERE, | 369 FROM_HERE, |
| 369 NewRunnableMethod(helper.get(), &PurgeMemoryTask::PurgeMemory)); | 370 base::Bind(&PurgeMemoryTask::PurgeMemory, helper.get())); |
| 370 } | 371 } |
| 371 | 372 |
| 372 MultiThreadedProxyResolver::Executor::~Executor() { | 373 MultiThreadedProxyResolver::Executor::~Executor() { |
| 373 // The important cleanup happens as part of Destroy(), which should always be | 374 // The important cleanup happens as part of Destroy(), which should always be |
| 374 // called first. | 375 // called first. |
| 375 DCHECK(!coordinator_) << "Destroy() was not called"; | 376 DCHECK(!coordinator_) << "Destroy() was not called"; |
| 376 DCHECK(!thread_.get()); | 377 DCHECK(!thread_.get()); |
| 377 DCHECK(!resolver_.get()); | 378 DCHECK(!resolver_.get()); |
| 378 DCHECK(!outstanding_job_); | 379 DCHECK(!outstanding_job_); |
| 379 } | 380 } |
| 380 | 381 |
| 381 // MultiThreadedProxyResolver -------------------------------------------------- | 382 // MultiThreadedProxyResolver -------------------------------------------------- |
| 382 | 383 |
| 383 MultiThreadedProxyResolver::MultiThreadedProxyResolver( | 384 MultiThreadedProxyResolver::MultiThreadedProxyResolver( |
| 384 ProxyResolverFactory* resolver_factory, | 385 ProxyResolverFactory* resolver_factory, |
| 385 size_t max_num_threads) | 386 size_t max_num_threads) |
| 386 : ProxyResolver(resolver_factory->resolvers_expect_pac_bytes()), | 387 : ProxyResolver(resolver_factory->resolvers_expect_pac_bytes()), |
| 387 resolver_factory_(resolver_factory), | 388 resolver_factory_(resolver_factory), |
| 388 max_num_threads_(max_num_threads) { | 389 max_num_threads_(max_num_threads) { |
| 389 DCHECK_GE(max_num_threads, 1u); | 390 DCHECK_GE(max_num_threads, 1u); |
| 390 } | 391 } |
| 391 | 392 |
| 392 MultiThreadedProxyResolver::~MultiThreadedProxyResolver() { | 393 MultiThreadedProxyResolver::~MultiThreadedProxyResolver() { |
| 393 // We will cancel all outstanding requests. | 394 // We will cancel all outstanding requests. |
| 394 pending_jobs_.clear(); | 395 pending_jobs_.clear(); |
| 395 ReleaseAllExecutors(); | 396 ReleaseAllExecutors(); |
| 396 } | 397 } |
| 397 | 398 |
| 398 int MultiThreadedProxyResolver::GetProxyForURL(const GURL& url, | 399 int MultiThreadedProxyResolver::GetProxyForURL( |
| 399 ProxyInfo* results, | 400 const GURL& url, ProxyInfo* results, const CompletionCallback& callback, |
| 400 OldCompletionCallback* callback, | 401 RequestHandle* request, const BoundNetLog& net_log) { |
| 401 RequestHandle* request, | |
| 402 const BoundNetLog& net_log) { | |
| 403 DCHECK(CalledOnValidThread()); | 402 DCHECK(CalledOnValidThread()); |
| 404 DCHECK(callback); | 403 DCHECK(!callback.is_null()); |
| 405 DCHECK(current_script_data_.get()) | 404 DCHECK(current_script_data_.get()) |
| 406 << "Resolver is un-initialized. Must call SetPacScript() first!"; | 405 << "Resolver is un-initialized. Must call SetPacScript() first!"; |
| 407 | 406 |
| 408 scoped_refptr<GetProxyForURLJob> job( | 407 scoped_refptr<GetProxyForURLJob> job( |
| 409 new GetProxyForURLJob(url, results, callback, net_log)); | 408 new GetProxyForURLJob(url, results, callback, net_log)); |
| 410 | 409 |
| 411 // Completion will be notified through |callback|, unless the caller cancels | 410 // Completion will be notified through |callback|, unless the caller cancels |
| 412 // the request using |request|. | 411 // the request using |request|. |
| 413 if (request) | 412 if (request) |
| 414 *request = reinterpret_cast<RequestHandle>(job.get()); | 413 *request = reinterpret_cast<RequestHandle>(job.get()); |
| 415 | 414 |
| 416 // If there is an executor that is ready to run this request, submit it! | 415 // If there is an executor that is ready to run this request, submit it! |
| 417 Executor* executor = FindIdleExecutor(); | 416 Executor* executor = FindIdleExecutor(); |
| 418 if (executor) { | 417 if (executor) { |
| 419 DCHECK_EQ(0u, pending_jobs_.size()); | 418 DCHECK_EQ(0u, pending_jobs_.size()); |
| 420 executor->StartJob(job); | 419 executor->StartJob(job); |
| 421 return ERR_IO_PENDING; | 420 return ERR_IO_PENDING; |
| 422 } | 421 } |
| 423 | 422 |
| 424 // Otherwise queue this request. (We will schedule it to a thread once one | 423 // Otherwise queue this request. (We will schedule it to a thread once one |
| 425 // becomes available). | 424 // becomes available). |
| 426 job->WaitingForThread(); | 425 job->WaitingForThread(); |
| 427 pending_jobs_.push_back(job); | 426 pending_jobs_.push_back(job); |
| 428 | 427 |
| 429 // If we haven't already reached the thread limit, provision a new thread to | 428 // If we haven't already reached the thread limit, provision a new thread to |
| 430 // drain the requests more quickly. | 429 // drain the requests more quickly. |
| 431 if (executors_.size() < max_num_threads_) { | 430 if (executors_.size() < max_num_threads_) { |
| 432 executor = AddNewExecutor(); | 431 executor = AddNewExecutor(); |
| 433 executor->StartJob( | 432 executor->StartJob( |
| 434 new SetPacScriptJob(current_script_data_, NULL)); | 433 new SetPacScriptJob(current_script_data_, CompletionCallback())); |
| 435 } | 434 } |
| 436 | 435 |
| 437 return ERR_IO_PENDING; | 436 return ERR_IO_PENDING; |
| 438 } | 437 } |
| 439 | 438 |
| 440 void MultiThreadedProxyResolver::CancelRequest(RequestHandle req) { | 439 void MultiThreadedProxyResolver::CancelRequest(RequestHandle req) { |
| 441 DCHECK(CalledOnValidThread()); | 440 DCHECK(CalledOnValidThread()); |
| 442 DCHECK(req); | 441 DCHECK(req); |
| 443 | 442 |
| 444 Job* job = reinterpret_cast<Job*>(req); | 443 Job* job = reinterpret_cast<Job*>(req); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 491 DCHECK(CalledOnValidThread()); | 490 DCHECK(CalledOnValidThread()); |
| 492 for (ExecutorList::iterator it = executors_.begin(); | 491 for (ExecutorList::iterator it = executors_.begin(); |
| 493 it != executors_.end(); ++it) { | 492 it != executors_.end(); ++it) { |
| 494 Executor* executor = *it; | 493 Executor* executor = *it; |
| 495 executor->PurgeMemory(); | 494 executor->PurgeMemory(); |
| 496 } | 495 } |
| 497 } | 496 } |
| 498 | 497 |
| 499 int MultiThreadedProxyResolver::SetPacScript( | 498 int MultiThreadedProxyResolver::SetPacScript( |
| 500 const scoped_refptr<ProxyResolverScriptData>& script_data, | 499 const scoped_refptr<ProxyResolverScriptData>& script_data, |
| 501 OldCompletionCallback* callback) { | 500 const CompletionCallback&callback) { |
| 502 DCHECK(CalledOnValidThread()); | 501 DCHECK(CalledOnValidThread()); |
| 503 DCHECK(callback); | 502 DCHECK(!callback.is_null()); |
| 504 | 503 |
| 505 // Save the script details, so we can provision new executors later. | 504 // Save the script details, so we can provision new executors later. |
| 506 current_script_data_ = script_data; | 505 current_script_data_ = script_data; |
| 507 | 506 |
| 508 // The user should not have any outstanding requests when they call | 507 // The user should not have any outstanding requests when they call |
| 509 // SetPacScript(). | 508 // SetPacScript(). |
| 510 CheckNoOutstandingUserRequests(); | 509 CheckNoOutstandingUserRequests(); |
| 511 | 510 |
| 512 // Destroy all of the current threads and their proxy resolvers. | 511 // Destroy all of the current threads and their proxy resolvers. |
| 513 ReleaseAllExecutors(); | 512 ReleaseAllExecutors(); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 578 return; | 577 return; |
| 579 | 578 |
| 580 // Get the next job to process (FIFO). Transfer it from the pending queue | 579 // Get the next job to process (FIFO). Transfer it from the pending queue |
| 581 // to the executor. | 580 // to the executor. |
| 582 scoped_refptr<Job> job = pending_jobs_.front(); | 581 scoped_refptr<Job> job = pending_jobs_.front(); |
| 583 pending_jobs_.pop_front(); | 582 pending_jobs_.pop_front(); |
| 584 executor->StartJob(job); | 583 executor->StartJob(job); |
| 585 } | 584 } |
| 586 | 585 |
| 587 } // namespace net | 586 } // namespace net |
| OLD | NEW |