| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
| 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_MULTI_THREADED_PROXY_RESOLVER_H_ | |
| 6 #define NET_PROXY_MULTI_THREADED_PROXY_RESOLVER_H_ | |
| 7 | |
| 8 #include <deque> | |
| 9 #include <vector> | |
| 10 | |
| 11 #include "base/basictypes.h" | |
| 12 #include "base/memory/ref_counted.h" | |
| 13 #include "base/memory/scoped_ptr.h" | |
| 14 #include "base/threading/non_thread_safe.h" | |
| 15 #include "net/base/net_export.h" | |
| 16 #include "net/proxy/proxy_resolver.h" | |
| 17 | |
| 18 namespace base { | |
| 19 class Thread; | |
| 20 } // namespace base | |
| 21 | |
| 22 namespace net { | |
| 23 | |
| 24 // ProxyResolverFactory is an interface for creating ProxyResolver instances. | |
| 25 class ProxyResolverFactory { | |
| 26 public: | |
| 27 explicit ProxyResolverFactory(bool resolvers_expect_pac_bytes) | |
| 28 : resolvers_expect_pac_bytes_(resolvers_expect_pac_bytes) {} | |
| 29 | |
| 30 virtual ~ProxyResolverFactory() {} | |
| 31 | |
| 32 // Creates a new ProxyResolver. The caller is responsible for freeing this | |
| 33 // object. | |
| 34 virtual ProxyResolver* CreateProxyResolver() = 0; | |
| 35 | |
| 36 bool resolvers_expect_pac_bytes() const { | |
| 37 return resolvers_expect_pac_bytes_; | |
| 38 } | |
| 39 | |
| 40 private: | |
| 41 bool resolvers_expect_pac_bytes_; | |
| 42 DISALLOW_COPY_AND_ASSIGN(ProxyResolverFactory); | |
| 43 }; | |
| 44 | |
| 45 // MultiThreadedProxyResolver is a ProxyResolver implementation that runs | |
| 46 // synchronous ProxyResolver implementations on worker threads. | |
| 47 // | |
| 48 // Threads are created lazily on demand, up to a maximum total. The advantage | |
| 49 // of having a pool of threads, is faster performance. In particular, being | |
| 50 // able to keep servicing PAC requests even if one blocks its execution. | |
| 51 // | |
| 52 // During initialization (SetPacScript), a single thread is spun up to test | |
| 53 // the script. If this succeeds, we cache the input script, and will re-use | |
| 54 // this to lazily provision any new threads as needed. | |
| 55 // | |
| 56 // For each new thread that we spawn, a corresponding new ProxyResolver is | |
| 57 // created using ProxyResolverFactory. | |
| 58 // | |
| 59 // Because we are creating multiple ProxyResolver instances, this means we | |
| 60 // are duplicating script contexts for what is ordinarily seen as being a | |
| 61 // single script. This can affect compatibility on some classes of PAC | |
| 62 // script: | |
| 63 // | |
| 64 // (a) Scripts whose initialization has external dependencies on network or | |
| 65 // time may end up successfully initializing on some threads, but not | |
| 66 // others. So depending on what thread services the request, the result | |
| 67 // may jump between several possibilities. | |
| 68 // | |
| 69 // (b) Scripts whose FindProxyForURL() depends on side-effects may now | |
| 70 // work differently. For example, a PAC script which was incrementing | |
| 71 // a global counter and using that to make a decision. In the | |
| 72 // multi-threaded model, each thread may have a different value for this | |
| 73 // counter, so it won't globally be seen as monotonically increasing! | |
| 74 class NET_EXPORT_PRIVATE MultiThreadedProxyResolver | |
| 75 : public ProxyResolver, | |
| 76 NON_EXPORTED_BASE(public base::NonThreadSafe) { | |
| 77 public: | |
| 78 // Creates an asynchronous ProxyResolver that runs requests on up to | |
| 79 // |max_num_threads|. | |
| 80 // | |
| 81 // For each thread that is created, an accompanying synchronous ProxyResolver | |
| 82 // will be provisioned using |resolver_factory|. All methods on these | |
| 83 // ProxyResolvers will be called on the one thread, with the exception of | |
| 84 // ProxyResolver::Shutdown() which will be called from the origin thread | |
| 85 // prior to destruction. | |
| 86 // | |
| 87 // The constructor takes ownership of |resolver_factory|. | |
| 88 MultiThreadedProxyResolver(ProxyResolverFactory* resolver_factory, | |
| 89 size_t max_num_threads); | |
| 90 | |
| 91 ~MultiThreadedProxyResolver() override; | |
| 92 | |
| 93 // ProxyResolver implementation: | |
| 94 int GetProxyForURL(const GURL& url, | |
| 95 ProxyInfo* results, | |
| 96 const CompletionCallback& callback, | |
| 97 RequestHandle* request, | |
| 98 const BoundNetLog& net_log) override; | |
| 99 void CancelRequest(RequestHandle request) override; | |
| 100 LoadState GetLoadState(RequestHandle request) const override; | |
| 101 void CancelSetPacScript() override; | |
| 102 int SetPacScript(const scoped_refptr<ProxyResolverScriptData>& script_data, | |
| 103 const CompletionCallback& callback) override; | |
| 104 | |
| 105 private: | |
| 106 class Executor; | |
| 107 class Job; | |
| 108 class SetPacScriptJob; | |
| 109 class GetProxyForURLJob; | |
| 110 // FIFO queue of pending jobs waiting to be started. | |
| 111 // TODO(eroman): Make this priority queue. | |
| 112 typedef std::deque<scoped_refptr<Job> > PendingJobsQueue; | |
| 113 typedef std::vector<scoped_refptr<Executor> > ExecutorList; | |
| 114 | |
| 115 // Asserts that there are no outstanding user-initiated jobs on any of the | |
| 116 // worker threads. | |
| 117 void CheckNoOutstandingUserRequests() const; | |
| 118 | |
| 119 // Stops and deletes all of the worker threads. | |
| 120 void ReleaseAllExecutors(); | |
| 121 | |
| 122 // Returns an idle worker thread which is ready to receive GetProxyForURL() | |
| 123 // requests. If all threads are occupied, returns NULL. | |
| 124 Executor* FindIdleExecutor(); | |
| 125 | |
| 126 // Creates a new worker thread, and appends it to |executors_|. | |
| 127 Executor* AddNewExecutor(); | |
| 128 | |
| 129 // Starts the next job from |pending_jobs_| if possible. | |
| 130 void OnExecutorReady(Executor* executor); | |
| 131 | |
| 132 const scoped_ptr<ProxyResolverFactory> resolver_factory_; | |
| 133 const size_t max_num_threads_; | |
| 134 PendingJobsQueue pending_jobs_; | |
| 135 ExecutorList executors_; | |
| 136 scoped_refptr<ProxyResolverScriptData> current_script_data_; | |
| 137 }; | |
| 138 | |
| 139 } // namespace net | |
| 140 | |
| 141 #endif // NET_PROXY_MULTI_THREADED_PROXY_RESOLVER_H_ | |
| OLD | NEW |