| // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 
 | // 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/ref_counted.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<Job*> jobs_; | 
 | }; | 
 |  | 
 | }  // namespace net | 
 |  | 
 | #endif  // NET_PROXY_RESOLUTION_MULTI_THREADED_PROXY_RESOLVER_H_ |