15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NET_PROXY_MULTI_THREADED_PROXY_RESOLVER_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NET_PROXY_MULTI_THREADED_PROXY_RESOLVER_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <deque> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/non_thread_safe.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_export.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_resolver.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Thread; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ProxyResolverFactory is an interface for creating ProxyResolver instances. 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ProxyResolverFactory { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit ProxyResolverFactory(bool resolvers_expect_pac_bytes) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : resolvers_expect_pac_bytes_(resolvers_expect_pac_bytes) {} 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~ProxyResolverFactory() {} 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Creates a new ProxyResolver. The caller is responsible for freeing this 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // object. 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ProxyResolver* CreateProxyResolver() = 0; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool resolvers_expect_pac_bytes() const { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return resolvers_expect_pac_bytes_; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool resolvers_expect_pac_bytes_; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ProxyResolverFactory); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MultiThreadedProxyResolver is a ProxyResolver implementation that runs 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// synchronous ProxyResolver implementations on worker threads. 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Threads are created lazily on demand, up to a maximum total. The advantage 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of having a pool of threads, is faster performance. In particular, being 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// able to keep servicing PAC requests even if one blocks its execution. 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// During initialization (SetPacScript), a single thread is spun up to test 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the script. If this succeeds, we cache the input script, and will re-use 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this to lazily provision any new threads as needed. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For each new thread that we spawn, a corresponding new ProxyResolver is 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// created using ProxyResolverFactory. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Because we are creating multiple ProxyResolver instances, this means we 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// are duplicating script contexts for what is ordinarily seen as being a 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// single script. This can affect compatibility on some classes of PAC 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// script: 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (a) Scripts whose initialization has external dependencies on network or 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// time may end up successfully initializing on some threads, but not 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// others. So depending on what thread services the request, the result 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// may jump between several possibilities. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (b) Scripts whose FindProxyForURL() depends on side-effects may now 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// work differently. For example, a PAC script which was incrementing 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a global counter and using that to make a decision. In the 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// multi-threaded model, each thread may have a different value for this 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// counter, so it won't globally be seen as monotonically increasing! 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NET_EXPORT_PRIVATE MultiThreadedProxyResolver 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : public ProxyResolver, 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NON_EXPORTED_BASE(public base::NonThreadSafe) { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Creates an asynchronous ProxyResolver that runs requests on up to 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |max_num_threads|. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For each thread that is created, an accompanying synchronous ProxyResolver 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will be provisioned using |resolver_factory|. All methods on these 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ProxyResolvers will be called on the one thread, with the exception of 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ProxyResolver::Shutdown() which will be called from the origin thread 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // prior to destruction. 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The constructor takes ownership of |resolver_factory|. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MultiThreadedProxyResolver(ProxyResolverFactory* resolver_factory, 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t max_num_threads); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~MultiThreadedProxyResolver(); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ProxyResolver implementation: 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual int GetProxyForURL(const GURL& url, 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProxyInfo* results, 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CompletionCallback& callback, 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RequestHandle* request, 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BoundNetLog& net_log) OVERRIDE; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void CancelRequest(RequestHandle request) OVERRIDE; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void CancelSetPacScript() OVERRIDE; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual int SetPacScript( 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const scoped_refptr<ProxyResolverScriptData>& script_data, 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CompletionCallback& callback) OVERRIDE; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class Executor; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class Job; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class SetPacScriptJob; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class GetProxyForURLJob; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FIFO queue of pending jobs waiting to be started. 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(eroman): Make this priority queue. 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::deque<scoped_refptr<Job> > PendingJobsQueue; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::vector<scoped_refptr<Executor> > ExecutorList; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Asserts that there are no outstanding user-initiated jobs on any of the 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // worker threads. 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void CheckNoOutstandingUserRequests() const; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Stops and deletes all of the worker threads. 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ReleaseAllExecutors(); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns an idle worker thread which is ready to receive GetProxyForURL() 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // requests. If all threads are occupied, returns NULL. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Executor* FindIdleExecutor(); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Creates a new worker thread, and appends it to |executors_|. 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Executor* AddNewExecutor(); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Starts the next job from |pending_jobs_| if possible. 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnExecutorReady(Executor* executor); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const scoped_ptr<ProxyResolverFactory> resolver_factory_; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t max_num_threads_; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PendingJobsQueue pending_jobs_; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExecutorList executors_; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<ProxyResolverScriptData> current_script_data_; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // NET_PROXY_MULTI_THREADED_PROXY_RESOLVER_H_ 143