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