1 // Copyright 2011 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef NET_PROXY_RESOLUTION_MULTI_THREADED_PROXY_RESOLVER_H_ 6 #define NET_PROXY_RESOLUTION_MULTI_THREADED_PROXY_RESOLVER_H_ 7 8 #include <stddef.h> 9 10 #include <memory> 11 #include <set> 12 13 #include "base/memory/scoped_refptr.h" 14 #include "net/base/completion_once_callback.h" 15 #include "net/base/net_export.h" 16 #include "net/proxy_resolution/proxy_resolver_factory.h" 17 18 namespace net { 19 class ProxyResolver; 20 21 // MultiThreadedProxyResolverFactory creates instances of a ProxyResolver 22 // implementation that runs synchronous ProxyResolver implementations on worker 23 // threads. 24 // 25 // Threads are created lazily on demand, up to a maximum total. The advantage 26 // of having a pool of threads, is faster performance. In particular, being 27 // able to keep servicing PAC requests even if one blocks its execution. 28 // 29 // During initialization (CreateProxyResolver), a single thread is spun up to 30 // test the script. If this succeeds, we cache the input script, and will re-use 31 // this to lazily provision any new threads as needed. 32 // 33 // For each new thread that we spawn in a particular MultiThreadedProxyResolver 34 // instance, a corresponding new ProxyResolver is created using the 35 // ProxyResolverFactory returned by CreateProxyResolverFactory(). 36 // 37 // Because we are creating multiple ProxyResolver instances, this means we 38 // are duplicating script contexts for what is ordinarily seen as being a 39 // single script. This can affect compatibility on some classes of PAC 40 // script: 41 // 42 // (a) Scripts whose initialization has external dependencies on network or 43 // time may end up successfully initializing on some threads, but not 44 // others. So depending on what thread services the request, the result 45 // may jump between several possibilities. 46 // 47 // (b) Scripts whose FindProxyForURL() depends on side-effects may now 48 // work differently. For example, a PAC script which was incrementing 49 // a global counter and using that to make a decision. In the 50 // multi-threaded model, each thread may have a different value for this 51 // counter, so it won't globally be seen as monotonically increasing! 52 class NET_EXPORT_PRIVATE MultiThreadedProxyResolverFactory 53 : public ProxyResolverFactory { 54 public: 55 MultiThreadedProxyResolverFactory(size_t max_num_threads, 56 bool factory_expects_bytes); 57 ~MultiThreadedProxyResolverFactory() override; 58 59 int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script, 60 std::unique_ptr<ProxyResolver>* resolver, 61 CompletionOnceCallback callback, 62 std::unique_ptr<Request>* request) override; 63 64 private: 65 class Job; 66 67 // Invoked to create a ProxyResolverFactory instance to pass to a 68 // MultiThreadedProxyResolver instance. 69 virtual std::unique_ptr<ProxyResolverFactory> 70 CreateProxyResolverFactory() = 0; 71 72 void RemoveJob(Job* job); 73 74 const size_t max_num_threads_; 75 76 std::set<Job*> jobs_; 77 }; 78 79 } // namespace net 80 81 #endif // NET_PROXY_RESOLUTION_MULTI_THREADED_PROXY_RESOLVER_H_ 82