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