Fixing build: GetViewContainer changed name from under me. :)
[chromium-blink-merge.git] / chrome / browser / cancelable_request.h
blob8513bcb98e66a87cf1f46e9df5636a5e9541e05c
1 // Copyright (c) 2006-2008 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.
5 // CancelableRequestProviders and Consumers work together to make requests that
6 // execute on a background thread in the provider and return data to the
7 // consumer. These class collaborate to keep a list of open requests and to
8 // make sure that requests to not outlive either of the objects involved in the
9 // transaction.
11 // If you do not need to return data to the consumer, do not use this system,
12 // just use the regular Task/RunnableMethod stuff.
14 // The CancelableRequest object is used internally to each provider to track
15 // request data and callback information.
17 // Example consumer calling |StartRequest| on a frontend service:
19 // class MyClass {
20 // void MakeRequest() {
21 // frontend_service->StartRequest(some_input1, some_input2, this,
22 // NewCallback(this, &MyClass:RequestComplete));
23 // }
25 // void RequestComplete(int status) {
26 // ...
27 // }
29 // private:
30 // CallbackConsumer callback_consumer_;
31 // };
34 // Example frontend provider. It receives requests and forwards them to the
35 // backend on another thread:
37 // class Frontend : public CancelableRequestProvider {
38 // typedef Callback1<int>::Type RequestCallbackType;
40 // Handle StartRequest(int some_input1, int some_input2,
41 // CallbackConsumer* consumer,
42 // RequestCallbackType* callback) {
43 // scoped_refptr<CancelableRequest<RequestCallbackType> > request(
44 // new CancelableRequest<RequestCallbackType>(callback));
45 // AddRequest(request, consumer);
47 // // Send the parameters and the request to the backend thread.
48 // backend_thread_->PostTask(FROM_HERE,
49 // NewRunnableMethod(backend_, &Backend::DoRequest, request,
50 // some_input1, some_input2));
52 // // The handle will have been set by AddRequest.
53 // return request->handle();
54 // }
55 // };
58 // Example backend provider that does work and dispatches the callback back
59 // to the original thread. Note that we need to pass it as a scoped_refptr so
60 // that the object will be kept alive if the request is canceled (releasing
61 // the provider's reference to it).
63 // class Backend {
64 // void DoRequest(
65 // scoped_refptr< CancelableRequest<Frontend::RequestCallbackType> >
66 // request,
67 // int some_input1, int some_input2) {
68 // if (request->canceled())
69 // return;
71 // ... do your processing ...
73 // // Depending on your typedefs, one of these two forms will be more
74 // // convenient:
75 // request->ForwardResult(Tuple1<int>(return_value));
77 // // -- or -- (inferior in this case)
78 // request->ForwardResult(Frontend::RequestCallbackType::TupleType(
79 // return_value));
80 // }
81 // };
83 #ifndef CHROME_BROWSER_CANCELABLE_REQUEST_H__
84 #define CHROME_BROWSER_CANCELABLE_REQUEST_H__
86 #include <map>
87 #include <vector>
89 #include "base/basictypes.h"
90 #include "base/lock.h"
91 #include "base/logging.h"
92 #include "base/message_loop.h"
93 #include "base/ref_counted.h"
94 #include "base/task.h"
96 class CancelableRequestBase;
97 class CancelableRequestConsumerBase;
99 // CancelableRequestProvider --------------------------------------------------
101 // This class is threadsafe. Requests may be added or canceled from any thread,
102 // but a task must only be canceled from the same thread it was initially run
103 // on.
105 // It is intended that providers inherit from this class to provide the
106 // necessary functionality.
108 class CancelableRequestProvider {
109 public:
110 // Identifies a specific request from this provider.
111 typedef int Handle;
113 CancelableRequestProvider();
114 virtual ~CancelableRequestProvider();
116 // Called by the enduser of the request to cancel it. This MUST be called on
117 // the same thread that originally issued the request (which is also the same
118 // thread that would have received the callback if it was not canceled).
119 void CancelRequest(Handle handle);
121 protected:
122 // Adds a new request and initializes it. This is called by a derived class
123 // to add a new request. The request's Init() will be called (which is why
124 // the consumer is required. The handle to the new request is returned.
125 Handle AddRequest(CancelableRequestBase* request,
126 CancelableRequestConsumerBase* consumer);
128 // Called by the CancelableRequest when the request has executed. It will
129 // be removed from the list of pending requests (as opposed to canceling,
130 // which will also set some state on the request).
131 void RequestCompleted(Handle handle);
133 private:
134 // Only call this when you already have acquired pending_request_lock_.
135 void CancelRequestLocked(Handle handle);
137 friend class CancelableRequestBase;
139 typedef std::map<Handle, scoped_refptr<CancelableRequestBase> >
140 CancelableRequestMap;
142 Lock pending_request_lock_;
144 // Lists all outstanding requests. Protected by the |lock_|.
145 CancelableRequestMap pending_requests_;
147 // The next handle value we will return. Protected by the |lock_|.
148 int next_handle_;
150 DISALLOW_EVIL_CONSTRUCTORS(CancelableRequestProvider);
153 // CancelableRequestConsumer --------------------------------------------------
155 // Classes wishing to make requests on a provider should have an instance of
156 // this class. Callers will need to pass a pointer to this consumer object
157 // when they make the request. It will automatically track any pending
158 // requests, and will automatically cancel them on destruction to prevent the
159 // accidental calling of freed memory.
161 // It is recommended to just have this class as a member variable since there
162 // is nothing to be gained by inheriting from it other than polluting your
163 // namespace.
165 // THIS CLASS IS NOT THREADSAFE (unlike the provider). You must make requests
166 // and get callbacks all from the same thread.
168 // Base class used to notify of new requests.
169 class CancelableRequestConsumerBase {
170 protected:
171 friend class CancelableRequestProvider;
173 virtual ~CancelableRequestConsumerBase() {
176 // Adds a new request to the list of requests that are being tracked. This
177 // is called by the provider when a new request is created.
178 virtual void OnRequestAdded(CancelableRequestProvider* provider,
179 CancelableRequestProvider::Handle handle) = 0;
181 // Removes the given request from the list of pending requests. Called
182 // by the CancelableRequest immediately after the callback has executed for a
183 // given request, and by the provider when a request is canceled.
184 virtual void OnRequestRemoved(CancelableRequestProvider* provider,
185 CancelableRequestProvider::Handle handle) = 0;
188 // Template for clients to use. It allows them to associate random "client
189 // data" with a specific requst. The default value for this type is given in
190 // |initial_t|. The type T should be small and easily copyable (like a pointer
191 // or an integer).
192 template<class T, T initial_t>
193 class CancelableRequestConsumerT : public CancelableRequestConsumerBase {
194 public:
195 CancelableRequestConsumerT() {
198 // Cancel any outstanding requests so that we do not get called back after we
199 // are destroyed. As these requests are removed, the providers will call us
200 // back on OnRequestRemoved, which will then update the list. To iterate
201 // successfully while the list is changing out from under us, we make a copy.
202 virtual ~CancelableRequestConsumerT() {
203 CancelAllRequests();
206 // Associates some random data with a specified request. The request MUST be
207 // outstanding, or it will assert. This is intended to be called immediately
208 // after a request is issued.
209 void SetClientData(CancelableRequestProvider* p,
210 CancelableRequestProvider::Handle h,
211 T client_data) {
212 PendingRequest request(p, h);
213 DCHECK(pending_requests_.find(request) != pending_requests_.end());
214 pending_requests_[request] = client_data;
217 // Retrieves previously associated data for a specified request. The request
218 // MUST be outstanding, or it will assert. This is intended to be called
219 // during processing of a callback to retrieve extra data.
220 T GetClientData(CancelableRequestProvider* p,
221 CancelableRequestProvider::Handle h) {
222 PendingRequest request(p, h);
223 DCHECK(pending_requests_.find(request) != pending_requests_.end());
224 return pending_requests_[request];
227 // Returns true if there are any pending requests.
228 bool HasPendingRequests() const {
229 return !pending_requests_.empty();
232 // Returns the number of pending requests.
233 size_t PendingRequestCount() const {
234 return pending_requests_.size();
237 // Cancels all requests outstanding.
238 void CancelAllRequests() {
239 PendingRequestList copied_requests(pending_requests_);
240 for (typename PendingRequestList::iterator i = copied_requests.begin();
241 i != copied_requests.end(); ++i)
242 i->first.provider->CancelRequest(i->first.handle);
243 copied_requests.clear();
245 // That should have cleared all the pending items.
246 DCHECK(pending_requests_.empty());
249 // Gets the client data for all pending requests.
250 void GetAllClientData(std::vector<T>* data) {
251 DCHECK(data);
252 for (typename PendingRequestList::iterator i = pending_requests_.begin();
253 i != pending_requests_.end(); ++i)
254 data->push_back(i->second);
257 protected:
258 struct PendingRequest {
259 PendingRequest(CancelableRequestProvider* p,
260 CancelableRequestProvider::Handle h)
261 : provider(p), handle(h) {
264 // Comparison operator for stl.
265 bool operator<(const PendingRequest& other) const {
266 if (provider != other.provider)
267 return provider < other.provider;
268 return handle < other.handle;
271 CancelableRequestProvider* provider;
272 CancelableRequestProvider::Handle handle;
274 typedef std::map<PendingRequest, T> PendingRequestList;
276 virtual void OnRequestAdded(CancelableRequestProvider* provider,
277 CancelableRequestProvider::Handle handle) {
278 DCHECK(pending_requests_.find(PendingRequest(provider, handle)) ==
279 pending_requests_.end());
280 pending_requests_[PendingRequest(provider, handle)] = initial_t;
283 virtual void OnRequestRemoved(CancelableRequestProvider* provider,
284 CancelableRequestProvider::Handle handle) {
285 typename PendingRequestList::iterator i =
286 pending_requests_.find(PendingRequest(provider, handle));
287 if (i == pending_requests_.end()) {
288 NOTREACHED() << "Got a complete notification for a nonexistant request";
289 return;
292 pending_requests_.erase(i);
295 // Lists all outstanding requests.
296 PendingRequestList pending_requests_;
299 // Some clients may not want to store data. Rather than do some complicated
300 // thing with virtual functions to allow some consumers to store extra data and
301 // some not to, we just define a default one that stores some dummy data.
302 typedef CancelableRequestConsumerT<int, 0> CancelableRequestConsumer;
304 // CancelableRequest ----------------------------------------------------------
306 // The request object that is used by a CancelableRequestProvider to send
307 // results to a CancelableRequestConsumer. This request handles the returning
308 // of results from a thread where the request is being executed to the thread
309 // and callback where the results are used. IT SHOULD BE PASSED AS A
310 // scoped_refptr TO KEEP IT ALIVE.
312 // It does not handle input parameters to the request. The caller must either
313 // transfer those separately or derive from this class to add the desired
314 // parameters.
316 // When the processing is complete on this message, the caller MUST call
317 // ForwardResult() with the return arguments that will be passed to the
318 // callback. If the request has been canceled, Return is optional (it will not
319 // do anything). If you do not have to return to the caller, the cancelable
320 // request system should not be used! (just use regular fire-and-forget tasks).
322 // Callback parameters are passed by value. In some cases, the request will
323 // want to return a large amount of data (for example, an image). One good
324 // approach is to derive from the CancelableRequest and make the data object
325 // (for example, a std::vector) owned by the CancelableRequest. The pointer
326 // to this data would be passed for the callback parameter. Since the
327 // CancelableRequest outlives the callback call, the data will be valid on the
328 // other thread for the callback, but will still be destroyed properly.
330 // Non-templatized base class that provides cancellation
331 class CancelableRequestBase :
332 public base::RefCountedThreadSafe<CancelableRequestBase> {
333 public:
334 friend class CancelableRequestProvider;
336 // Initializes most things to empty, Init() must be called to complete
337 // initialization of the object. This will be done by the provider when
338 // the request is dispatched.
340 // This must be called on the same thread the callback will be executed on,
341 // it will save that thread for later.
343 // This two-phase init is done so that the constructor can have no
344 // parameters, which makes it much more convenient for derived classes,
345 // which can be common. The derived classes need only declare the variables
346 // they provide in the constructor rather than many lines of internal
347 // tracking data that are passed to the base class (us).
349 // In addition, not all of the information (for example, the handle) is known
350 // at construction time.
351 CancelableRequestBase()
352 : provider_(NULL),
353 consumer_(NULL),
354 handle_(0),
355 canceled_(false) {
356 callback_thread_ = MessageLoop::current();
358 virtual ~CancelableRequestBase() {
361 CancelableRequestConsumerBase* consumer() const {
362 return consumer_;
365 CancelableRequestProvider::Handle handle() const {
366 return handle_;
369 // The canceled flag indicates that the request should not be executed.
370 // A request can never be uncanceled, so only a setter for true is provided.
371 void set_canceled() {
372 canceled_ = true;
374 bool canceled() {
375 return canceled_;
378 protected:
379 // Initializes the object with the particulars from the provider. It may only
380 // be called once (it is called by the provider, which is a friend).
381 void Init(CancelableRequestProvider* provider,
382 CancelableRequestProvider::Handle handle,
383 CancelableRequestConsumerBase* consumer) {
384 DCHECK(handle_ == 0 && provider_ == NULL && consumer_ == NULL);
385 provider_ = provider;
386 consumer_ = consumer;
387 handle_ = handle;
390 // Tells the provider that the request is complete, which then tells the
391 // consumer.
392 void NotifyCompleted() const {
393 provider_->RequestCompleted(handle());
396 // The message loop that this request was created on. The callback will
397 // happen on the same thread.
398 MessageLoop* callback_thread_;
400 // The provider for this request. When we execute, we will notify this that
401 // request is complete to it can remove us from the requests it tracks.
402 CancelableRequestProvider* provider_;
404 // Notified after we execute that the request is complete. This should only
405 // be accessed if !canceled_, otherwise the pointer is invalid.
406 CancelableRequestConsumerBase* consumer_;
408 // The handle to this request inside the provider. This will be initialized
409 // to 0 when the request is created, and the provider will set it once the
410 // request has been dispatched.
411 CancelableRequestProvider::Handle handle_;
413 // Set if the caller cancels this request. No callbacks should be made when
414 // this is set.
415 bool canceled_;
417 private:
418 DISALLOW_EVIL_CONSTRUCTORS(CancelableRequestBase);
421 // Templatized class. This is the one you should use directly or inherit from.
422 // The callback can be invoked by calling the ForwardResult() method. For this,
423 // you must either pack the parameters into a tuple, or use DispatchToMethod
424 // (in tuple.h).
426 // If you inherit to add additional input parameters or to do more complex
427 // memory management (see the bigger comment about this above), you can put
428 // those on a subclass of this.
430 // We have decided to allow users to treat derived classes of this as structs,
431 // so you can add members without getters and setters (which just makes the
432 // code harder to read). Don't use underscores after these vars. For example:
434 // typedef Callback1<int>::Type DoodieCallback;
436 // class DoodieRequest : public CancelableRequest<DoodieCallback> {
437 // public:
438 // DoodieRequest(CallbackType* callback) : CancelableRequest(callback) {
439 // }
441 // int input_arg1;
442 // std::wstring input_arg2;
443 // };
444 template<typename CB>
445 class CancelableRequest : public CancelableRequestBase {
446 public:
447 typedef CB CallbackType; // CallbackRunner<...>
448 typedef typename CB::TupleType TupleType; // Tuple of the callback args.
450 // The provider MUST call Init() (on the base class) before this is valid.
451 // This class will take ownership of the callback object and destroy it when
452 // appropriate.
453 explicit CancelableRequest(CallbackType* callback)
454 : CancelableRequestBase(),
455 callback_(callback) {
456 DCHECK(callback) << "We should always have a callback";
458 virtual ~CancelableRequest() {
461 // Dispatches the parameters to the correct thread so the callback can be
462 // executed there. The caller does not need to check for cancel before
463 // calling this. It is optional in the cancelled case. In the non-cancelled
464 // case, this MUST be called.
466 // If there are any pointers in the parameters, they must live at least as
467 // long as the request so that it can be forwarded to the other thread.
468 // For complex objects, this would typically be done by having a derived
469 // request own the data itself.
470 void ForwardResult(const TupleType& param) {
471 DCHECK(callback_.get());
472 if (!canceled()) {
473 if (callback_thread_ == MessageLoop::current()) {
474 // We can do synchronous callbacks when we're on the same thread.
475 ExecuteCallback(param);
476 } else {
477 callback_thread_->PostTask(FROM_HERE, NewRunnableMethod(this,
478 &CancelableRequest<CB>::ExecuteCallback, param));
483 private:
484 // Executes the callback and notifies the provider and the consumer that this
485 // request has been completed. This must be called on the callback_thread_.
486 void ExecuteCallback(const TupleType& param) {
487 if (!canceled_) {
488 // Execute the callback.
489 callback_->RunWithParams(param);
491 // Notify the provider that the request is complete. The provider will
492 // notify the consumer for us.
493 NotifyCompleted();
497 // This should only be executed if !canceled_, otherwise the pointers may be
498 // invalid.
499 scoped_ptr<CallbackType> callback_;
502 // A CancelableRequest with a single value. This is intended for use when
503 // the provider provides a single value. The provider fills the result into
504 // the value, and notifies the request with a pointer to the value. For example,
505 // HistoryService has many methods that callback with a vector. Use the
506 // following pattern for this:
507 // 1. Define the callback:
508 // typedef Callback2<Handle, std::vector<Foo>*>::Type FooCallback;
509 // 2. Define the CancelableRequest1 type.
510 // typedef CancelableRequest1<FooCallback, std::vector<Foo>> FooRequest;
511 // 3. The provider method should then fillin the contents of the vector,
512 // forwarding the result like so:
513 // request->ForwardResult(FooRequest::TupleType(request->handle(),
514 // &request->value));
516 // Tip: for passing more than one value, use a Tuple for the value.
517 template<typename CB, typename Type>
518 class CancelableRequest1 : public CancelableRequest<CB> {
519 public:
520 explicit CancelableRequest1(
521 typename CancelableRequest<CB>::CallbackType* callback)
522 : CancelableRequest<CB>(callback) {
525 virtual ~CancelableRequest1() {
528 // The value.
529 Type value;
532 #endif // CHROME_BROWSER_CANCELABLE_REQUEST_H__