OLD | NEW |
| (Empty) |
1 // Copyright (c) 2009 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 <string> | |
10 #include <vector> | |
11 | |
12 #include "base/basictypes.h" | |
13 #include "base/non_thread_safe.h" | |
14 #include "base/ref_counted.h" | |
15 #include "base/scoped_ptr.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 MultiThreadedProxyResolver : public ProxyResolver, public NonThreadSafe { | |
75 public: | |
76 // Creates an asynchronous ProxyResolver that runs requests on up to | |
77 // |max_num_threads|. | |
78 // | |
79 // For each thread that is created, an accompanying synchronous ProxyResolver | |
80 // will be provisioned using |resolver_factory|. All methods on these | |
81 // ProxyResolvers will be called on the one thread, with the exception of | |
82 // ProxyResolver::Shutdown() which will be called from the origin thread | |
83 // prior to destruction. | |
84 // | |
85 // The constructor takes ownership of |resolver_factory|. | |
86 MultiThreadedProxyResolver(ProxyResolverFactory* resolver_factory, | |
87 size_t max_num_threads); | |
88 | |
89 virtual ~MultiThreadedProxyResolver(); | |
90 | |
91 // ProxyResolver implementation: | |
92 virtual int GetProxyForURL(const GURL& url, | |
93 ProxyInfo* results, | |
94 CompletionCallback* callback, | |
95 RequestHandle* request, | |
96 const BoundNetLog& net_log); | |
97 virtual void CancelRequest(RequestHandle request); | |
98 virtual void CancelSetPacScript(); | |
99 virtual void PurgeMemory(); | |
100 | |
101 private: | |
102 class Executor; | |
103 class Job; | |
104 class SetPacScriptJob; | |
105 class GetProxyForURLJob; | |
106 // FIFO queue of pending jobs waiting to be started. | |
107 // TODO(eroman): Make this priority queue. | |
108 typedef std::deque<scoped_refptr<Job> > PendingJobsQueue; | |
109 typedef std::vector<scoped_refptr<Executor> > ExecutorList; | |
110 | |
111 // ProxyResolver implementation: | |
112 virtual int SetPacScript(const GURL& pac_url, | |
113 const string16& pac_script, | |
114 CompletionCallback* callback); | |
115 | |
116 // Asserts that there are no outstanding user-initiated jobs on any of the | |
117 // worker threads. | |
118 void CheckNoOutstandingUserRequests() const; | |
119 | |
120 // Stops and deletes all of the worker threads. | |
121 void ReleaseAllExecutors(); | |
122 | |
123 // Returns an idle worker thread which is ready to receive GetProxyForURL() | |
124 // requests. If all threads are occupied, returns NULL. | |
125 Executor* FindIdleExecutor(); | |
126 | |
127 // Creates a new worker thread, and appends it to |executors_|. | |
128 Executor* AddNewExecutor(); | |
129 | |
130 // Starts the next job from |pending_jobs_| if possible. | |
131 void OnExecutorReady(Executor* executor); | |
132 | |
133 const scoped_ptr<ProxyResolverFactory> resolver_factory_; | |
134 const size_t max_num_threads_; | |
135 PendingJobsQueue pending_jobs_; | |
136 ExecutorList executors_; | |
137 bool was_set_pac_script_called_; | |
138 GURL current_pac_url_; | |
139 string16 current_pac_script_; | |
140 }; | |
141 | |
142 } // namespace net | |
143 | |
144 #endif // NET_PROXY_MULTI_THREADED_PROXY_RESOLVER_H_ | |
OLD | NEW |