Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(129)

Side by Side Diff: net/proxy/multi_threaded_proxy_resolver.h

Issue 2822043: Add the capability to run multiple proxy PAC scripts in parallel.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Re-upload after revert Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/net.gyp ('k') | net/proxy/multi_threaded_proxy_resolver.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef NET_PROXY_SINGLE_THREADED_PROXY_RESOLVER_H_ 5 #ifndef NET_PROXY_MULTI_THREADED_PROXY_RESOLVER_H_
6 #define NET_PROXY_SINGLE_THREADED_PROXY_RESOLVER_H_ 6 #define NET_PROXY_MULTI_THREADED_PROXY_RESOLVER_H_
7 7
8 #include <deque> 8 #include <deque>
9 #include <string> 9 #include <string>
10 #include <vector>
10 11
12 #include "base/basictypes.h"
13 #include "base/non_thread_safe.h"
11 #include "base/ref_counted.h" 14 #include "base/ref_counted.h"
12 #include "base/scoped_ptr.h" 15 #include "base/scoped_ptr.h"
13 #include "net/proxy/proxy_resolver.h" 16 #include "net/proxy/proxy_resolver.h"
14 17
15 namespace base { 18 namespace base {
16 class Thread; 19 class Thread;
17 } // namespace base 20 } // namespace base
18 21
19 namespace net { 22 namespace net {
20 23
21 // ProxyResolver implementation that wraps a synchronous ProxyResolver, and 24 // ProxyResolverFactory is an interface for creating ProxyResolver instances.
22 // runs it on a single worker thread. If multiple requests accumulate, they 25 class ProxyResolverFactory {
23 // are serviced in FIFO order.
24 class SingleThreadedProxyResolver : public ProxyResolver {
25 public: 26 public:
26 // |resolver| is a synchronous ProxyResolver implementation. It doesn't 27 explicit ProxyResolverFactory(bool resolvers_expect_pac_bytes)
27 // have to be thread-safe, since it is run on exactly one thread. The 28 : resolvers_expect_pac_bytes_(resolvers_expect_pac_bytes) {}
28 // constructor takes ownership of |resolver|.
29 explicit SingleThreadedProxyResolver(ProxyResolver* resolver);
30 29
31 virtual ~SingleThreadedProxyResolver(); 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();
32 90
33 // ProxyResolver implementation: 91 // ProxyResolver implementation:
34 virtual int GetProxyForURL(const GURL& url, 92 virtual int GetProxyForURL(const GURL& url,
35 ProxyInfo* results, 93 ProxyInfo* results,
36 CompletionCallback* callback, 94 CompletionCallback* callback,
37 RequestHandle* request, 95 RequestHandle* request,
38 const BoundNetLog& net_log); 96 const BoundNetLog& net_log);
39 virtual void CancelRequest(RequestHandle request); 97 virtual void CancelRequest(RequestHandle request);
40 virtual void CancelSetPacScript(); 98 virtual void CancelSetPacScript();
41 virtual void PurgeMemory(); 99 virtual void PurgeMemory();
42 100
43 protected:
44 // The wrapped (synchronous) ProxyResolver.
45 ProxyResolver* resolver() { return resolver_.get(); }
46
47 private: 101 private:
48 // Refcounted helper class that bridges between origin thread and worker 102 class Executor;
49 // thread.
50 class Job; 103 class Job;
51 friend class Job; 104 class SetPacScriptJob;
52 class SetPacScriptTask; 105 class GetProxyForURLJob;
53 friend class SetPacScriptTask; 106 // FIFO queue of pending jobs waiting to be started.
54 // FIFO queue that contains the in-progress job, and any pending jobs. 107 // TODO(eroman): Make this priority queue.
55 typedef std::deque<scoped_refptr<Job> > PendingJobsQueue; 108 typedef std::deque<scoped_refptr<Job> > PendingJobsQueue;
56 109 typedef std::vector<scoped_refptr<Executor> > ExecutorList;
57 base::Thread* thread() { return thread_.get(); }
58 110
59 // ProxyResolver implementation: 111 // ProxyResolver implementation:
60 virtual int SetPacScript(const GURL& pac_url, 112 virtual int SetPacScript(const GURL& pac_url,
61 const string16& pac_script, 113 const string16& pac_script,
62 CompletionCallback* callback); 114 CompletionCallback* callback);
63 115
64 // Starts the worker thread if it isn't already running. 116 // Asserts that there are no outstanding user-initiated jobs on any of the
65 void EnsureThreadStarted(); 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();
66 129
67 // Starts the next job from |pending_jobs_| if possible. 130 // Starts the next job from |pending_jobs_| if possible.
68 void ProcessPendingJobs(); 131 void OnExecutorReady(Executor* executor);
69 132
70 // Removes the front entry of the jobs queue. |expected_job| is our 133 const scoped_ptr<ProxyResolverFactory> resolver_factory_;
71 // expectation of what the front of the job queue is; it is only used by 134 const size_t max_num_threads_;
72 // DCHECK for verification purposes.
73 void RemoveFrontOfJobsQueueAndStartNext(Job* expected_job);
74
75 // Clears |outstanding_set_pac_script_task_|.
76 // Called when |task| has just finished.
77 void RemoveOutstandingSetPacScriptTask(SetPacScriptTask* task);
78
79 // The synchronous resolver implementation.
80 scoped_ptr<ProxyResolver> resolver_;
81
82 // The thread where |resolver_| is run on.
83 // Note that declaration ordering is important here. |thread_| needs to be
84 // destroyed *before* |resolver_|, in case |resolver_| is currently
85 // executing on |thread_|.
86 scoped_ptr<base::Thread> thread_;
87
88 PendingJobsQueue pending_jobs_; 135 PendingJobsQueue pending_jobs_;
89 scoped_refptr<SetPacScriptTask> outstanding_set_pac_script_task_; 136 ExecutorList executors_;
137 bool was_set_pac_script_called_;
138 GURL current_pac_url_;
139 string16 current_pac_script_;
90 }; 140 };
91 141
92 } // namespace net 142 } // namespace net
93 143
94 #endif // NET_PROXY_SINGLE_THREADED_PROXY_RESOLVER_H_ 144 #endif // NET_PROXY_MULTI_THREADED_PROXY_RESOLVER_H_
OLDNEW
« no previous file with comments | « net/net.gyp ('k') | net/proxy/multi_threaded_proxy_resolver.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698