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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/net.gyp ('k') | net/proxy/multi_threaded_proxy_resolver.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/proxy/multi_threaded_proxy_resolver.h
===================================================================
--- net/proxy/multi_threaded_proxy_resolver.h (revision 51914)
+++ net/proxy/multi_threaded_proxy_resolver.h (working copy)
@@ -2,12 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_PROXY_SINGLE_THREADED_PROXY_RESOLVER_H_
-#define NET_PROXY_SINGLE_THREADED_PROXY_RESOLVER_H_
+#ifndef NET_PROXY_MULTI_THREADED_PROXY_RESOLVER_H_
+#define NET_PROXY_MULTI_THREADED_PROXY_RESOLVER_H_
#include <deque>
#include <string>
+#include <vector>
+#include "base/basictypes.h"
+#include "base/non_thread_safe.h"
#include "base/ref_counted.h"
#include "base/scoped_ptr.h"
#include "net/proxy/proxy_resolver.h"
@@ -18,18 +21,73 @@
namespace net {
-// ProxyResolver implementation that wraps a synchronous ProxyResolver, and
-// runs it on a single worker thread. If multiple requests accumulate, they
-// are serviced in FIFO order.
-class SingleThreadedProxyResolver : public ProxyResolver {
+// ProxyResolverFactory is an interface for creating ProxyResolver instances.
+class ProxyResolverFactory {
public:
- // |resolver| is a synchronous ProxyResolver implementation. It doesn't
- // have to be thread-safe, since it is run on exactly one thread. The
- // constructor takes ownership of |resolver|.
- explicit SingleThreadedProxyResolver(ProxyResolver* resolver);
+ explicit ProxyResolverFactory(bool resolvers_expect_pac_bytes)
+ : resolvers_expect_pac_bytes_(resolvers_expect_pac_bytes) {}
- virtual ~SingleThreadedProxyResolver();
+ virtual ~ProxyResolverFactory() {}
+ // Creates a new ProxyResolver. The caller is responsible for freeing this
+ // object.
+ virtual ProxyResolver* CreateProxyResolver() = 0;
+
+ bool resolvers_expect_pac_bytes() const {
+ return resolvers_expect_pac_bytes_;
+ }
+
+ private:
+ bool resolvers_expect_pac_bytes_;
+ DISALLOW_COPY_AND_ASSIGN(ProxyResolverFactory);
+};
+
+// MultiThreadedProxyResolver is 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 (SetPacScript), 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, a corresponding new ProxyResolver is
+// created using ProxyResolverFactory.
+//
+// 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 MultiThreadedProxyResolver : public ProxyResolver, public NonThreadSafe {
+ public:
+ // Creates an asynchronous ProxyResolver that runs requests on up to
+ // |max_num_threads|.
+ //
+ // For each thread that is created, an accompanying synchronous ProxyResolver
+ // will be provisioned using |resolver_factory|. All methods on these
+ // ProxyResolvers will be called on the one thread, with the exception of
+ // ProxyResolver::Shutdown() which will be called from the origin thread
+ // prior to destruction.
+ //
+ // The constructor takes ownership of |resolver_factory|.
+ MultiThreadedProxyResolver(ProxyResolverFactory* resolver_factory,
+ size_t max_num_threads);
+
+ virtual ~MultiThreadedProxyResolver();
+
// ProxyResolver implementation:
virtual int GetProxyForURL(const GURL& url,
ProxyInfo* results,
@@ -40,55 +98,47 @@
virtual void CancelSetPacScript();
virtual void PurgeMemory();
- protected:
- // The wrapped (synchronous) ProxyResolver.
- ProxyResolver* resolver() { return resolver_.get(); }
-
private:
- // Refcounted helper class that bridges between origin thread and worker
- // thread.
+ class Executor;
class Job;
- friend class Job;
- class SetPacScriptTask;
- friend class SetPacScriptTask;
- // FIFO queue that contains the in-progress job, and any pending jobs.
+ class SetPacScriptJob;
+ class GetProxyForURLJob;
+ // FIFO queue of pending jobs waiting to be started.
+ // TODO(eroman): Make this priority queue.
typedef std::deque<scoped_refptr<Job> > PendingJobsQueue;
+ typedef std::vector<scoped_refptr<Executor> > ExecutorList;
- base::Thread* thread() { return thread_.get(); }
-
// ProxyResolver implementation:
virtual int SetPacScript(const GURL& pac_url,
const string16& pac_script,
CompletionCallback* callback);
- // Starts the worker thread if it isn't already running.
- void EnsureThreadStarted();
+ // Asserts that there are no outstanding user-initiated jobs on any of the
+ // worker threads.
+ void CheckNoOutstandingUserRequests() const;
- // Starts the next job from |pending_jobs_| if possible.
- void ProcessPendingJobs();
+ // Stops and deletes all of the worker threads.
+ void ReleaseAllExecutors();
- // Removes the front entry of the jobs queue. |expected_job| is our
- // expectation of what the front of the job queue is; it is only used by
- // DCHECK for verification purposes.
- void RemoveFrontOfJobsQueueAndStartNext(Job* expected_job);
+ // Returns an idle worker thread which is ready to receive GetProxyForURL()
+ // requests. If all threads are occupied, returns NULL.
+ Executor* FindIdleExecutor();
- // Clears |outstanding_set_pac_script_task_|.
- // Called when |task| has just finished.
- void RemoveOutstandingSetPacScriptTask(SetPacScriptTask* task);
+ // Creates a new worker thread, and appends it to |executors_|.
+ Executor* AddNewExecutor();
- // The synchronous resolver implementation.
- scoped_ptr<ProxyResolver> resolver_;
+ // Starts the next job from |pending_jobs_| if possible.
+ void OnExecutorReady(Executor* executor);
- // The thread where |resolver_| is run on.
- // Note that declaration ordering is important here. |thread_| needs to be
- // destroyed *before* |resolver_|, in case |resolver_| is currently
- // executing on |thread_|.
- scoped_ptr<base::Thread> thread_;
-
+ const scoped_ptr<ProxyResolverFactory> resolver_factory_;
+ const size_t max_num_threads_;
PendingJobsQueue pending_jobs_;
- scoped_refptr<SetPacScriptTask> outstanding_set_pac_script_task_;
+ ExecutorList executors_;
+ bool was_set_pac_script_called_;
+ GURL current_pac_url_;
+ string16 current_pac_script_;
};
} // namespace net
-#endif // NET_PROXY_SINGLE_THREADED_PROXY_RESOLVER_H_
+#endif // NET_PROXY_MULTI_THREADED_PROXY_RESOLVER_H_
« 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