| // Copyright 2011 The Chromium Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef NET_PROXY_RESOLUTION_MULTI_THREADED_PROXY_RESOLVER_H_ | |
| #define NET_PROXY_RESOLUTION_MULTI_THREADED_PROXY_RESOLVER_H_ | |
| #include <stddef.h> | |
| #include <memory> | |
| #include <set> | |
| #include "base/memory/raw_ptr.h" | |
| #include "base/memory/scoped_refptr.h" | |
| #include "net/base/completion_once_callback.h" | |
| #include "net/base/net_export.h" | |
| #include "net/proxy_resolution/proxy_resolver_factory.h" | |
| namespace net { | |
| class ProxyResolver; | |
| // MultiThreadedProxyResolverFactory creates instances of a ProxyResolver | |
| // implementation that runs synchronous ProxyResolver implementations on worker | |
| // threads. | |
| // | |
| // Threads are created lazily on demand, up to a maximum total. The advantage | |
| // of having a pool of threads, is faster performance. In particular, being | |
| // able to keep servicing PAC requests even if one blocks its execution. | |
| // | |
| // During initialization (CreateProxyResolver), a single thread is spun up to | |
| // test the script. If this succeeds, we cache the input script, and will re-use | |
| // this to lazily provision any new threads as needed. | |
| // | |
| // For each new thread that we spawn in a particular MultiThreadedProxyResolver | |
| // instance, a corresponding new ProxyResolver is created using the | |
| // ProxyResolverFactory returned by CreateProxyResolverFactory(). | |
| // | |
| // Because we are creating multiple ProxyResolver instances, this means we | |
| // are duplicating script contexts for what is ordinarily seen as being a | |
| // single script. This can affect compatibility on some classes of PAC | |
| // script: | |
| // | |
| // (a) Scripts whose initialization has external dependencies on network or | |
| // time may end up successfully initializing on some threads, but not | |
| // others. So depending on what thread services the request, the result | |
| // may jump between several possibilities. | |
| // | |
| // (b) Scripts whose FindProxyForURL() depends on side-effects may now | |
| // work differently. For example, a PAC script which was incrementing | |
| // a global counter and using that to make a decision. In the | |
| // multi-threaded model, each thread may have a different value for this | |
| // counter, so it won't globally be seen as monotonically increasing! | |
| class NET_EXPORT_PRIVATE MultiThreadedProxyResolverFactory | |
| : public ProxyResolverFactory { | |
| public: | |
| MultiThreadedProxyResolverFactory(size_t max_num_threads, | |
| bool factory_expects_bytes); | |
| ~MultiThreadedProxyResolverFactory() override; | |
| int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script, | |
| std::unique_ptr<ProxyResolver>* resolver, | |
| CompletionOnceCallback callback, | |
| std::unique_ptr<Request>* request) override; | |
| private: | |
| class Job; | |
| // Invoked to create a ProxyResolverFactory instance to pass to a | |
| // MultiThreadedProxyResolver instance. | |
| virtual std::unique_ptr<ProxyResolverFactory> | |
| CreateProxyResolverFactory() = 0; | |
| void RemoveJob(Job* job); | |
| const size_t max_num_threads_; | |
| std::set<raw_ptr<Job, SetExperimental>> jobs_; | |
| }; | |
| } // namespace net | |
| #endif // NET_PROXY_RESOLUTION_MULTI_THREADED_PROXY_RESOLVER_H_ |