• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 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 // 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 classes collaborate to keep a list of open requests and to
8 // make sure that requests do not outlive either of the objects involved in the
9 // transaction.
10 //
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.
13 //
14 // The CancelableRequest object is used internally to each provider to track
15 // request data and callback information.
16 //
17 // Example consumer calling |StartRequest| on a frontend service:
18 //
19 //   class MyClass {
20 //     void MakeRequest() {
21 //       frontend_service->StartRequest(
22 //           some_input1, some_input2,
23 //           &callback_consumer_,
24 //           base::Bind(&MyClass:RequestComplete, base::Unretained(this)));
25 //       // StartRequest() returns a Handle which may be retained for use with
26 //       // CancelRequest() if required, e.g. in MyClass's destructor.
27 //     }
28 //
29 //     void RequestComplete(int status) {
30 //       ...
31 //     }
32 //
33 //    private:
34 //     CancelableRequestConsumer callback_consumer_;
35 //   };
36 //
37 //
38 // Example frontend provider. It receives requests and forwards them to the
39 // backend on another thread:
40 //
41 //   class Frontend : public CancelableRequestProvider {
42 //     typedef Callback1<int>::Type RequestCallbackType;
43 //
44 //     Handle StartRequest(int some_input1, int some_input2,
45 //                         CancelableRequestConsumerBase* consumer,
46 //                         RequestCallbackType* callback) {
47 //       scoped_refptr<CancelableRequest<RequestCallbackType> > request(
48 //           new CancelableRequest<RequestCallbackType>(callback));
49 //       AddRequest(request, consumer);
50 //
51 //       // Send the parameters and the request to the backend thread.
52 //       backend_thread_->PostTask(
53 //           FROM_HERE,
54 //           base::Bind(&Backend::DoRequest, backend_, request,
55 //                             some_input1, some_input2));
56 //
57 //       // The handle will have been set by AddRequest.
58 //       return request->handle();
59 //     }
60 //   };
61 //
62 //
63 // Example backend provider that does work and dispatches the callback back
64 // to the original thread. Note that we need to pass it as a scoped_refptr so
65 // that the object will be kept alive if the request is canceled (releasing
66 // the provider's reference to it).
67 //
68 //   class Backend {
69 //     void DoRequest(
70 //         scoped_refptr< CancelableRequest<Frontend::RequestCallbackType> >
71 //             request,
72 //         int some_input1, int some_input2) {
73 //       if (request->canceled())
74 //         return;
75 //
76 //       ... do your processing ...
77 //
78 //       // Depending on your typedefs, one of these two forms will be more
79 //       // convenient:
80 //       request->ForwardResult(Tuple1<int>(return_value));
81 //
82 //       // -- or --  (inferior in this case)
83 //       request->ForwardResult(Frontend::RequestCallbackType::TupleType(
84 //           return_value));
85 //     }
86 //   };
87 
88 #ifndef CHROME_BROWSER_COMMON_CANCELABLE_REQUEST_H_
89 #define CHROME_BROWSER_COMMON_CANCELABLE_REQUEST_H_
90 
91 #include <map>
92 #include <vector>
93 
94 #include "base/basictypes.h"
95 #include "base/bind.h"
96 #include "base/callback.h"
97 #include "base/callback_internal.h"
98 #include "base/logging.h"
99 #include "base/memory/ref_counted.h"
100 #include "base/memory/scoped_ptr.h"
101 #include "base/message_loop/message_loop.h"
102 #include "base/synchronization/cancellation_flag.h"
103 #include "base/synchronization/lock.h"
104 #include "build/build_config.h"
105 
106 class CancelableRequestBase;
107 class CancelableRequestConsumerBase;
108 
109 // CancelableRequestProvider --------------------------------------------------
110 //
111 // This class is threadsafe. Requests may be added or canceled from any thread,
112 // but a task must only be canceled from the same thread it was initially run
113 // on.
114 //
115 // It is intended that providers inherit from this class to provide the
116 // necessary functionality.
117 
118 class CancelableRequestProvider {
119  public:
120   // Identifies a specific request from this provider.
121   typedef int Handle;
122 
123   CancelableRequestProvider();
124 
125   // Called by the enduser of the request to cancel it. This MUST be called on
126   // the same thread that originally issued the request (which is also the same
127   // thread that would have received the callback if it was not canceled).
128   // handle must be for a valid pending (not yet complete or cancelled) request.
129   void CancelRequest(Handle handle);
130 
131  protected:
132   virtual ~CancelableRequestProvider();
133 
134   // Adds a new request and initializes it. This is called by a derived class
135   // to add a new request. The request's Init() will be called (which is why
136   // the consumer is required. The handle to the new request is returned.
137   Handle AddRequest(CancelableRequestBase* request,
138                     CancelableRequestConsumerBase* consumer);
139 
140   // Called by the CancelableRequest when the request has executed. It will
141   // be removed from the list of pending requests (as opposed to canceling,
142   // which will also set some state on the request).
143   void RequestCompleted(Handle handle);
144 
145  private:
146   typedef std::map<Handle, scoped_refptr<CancelableRequestBase> >
147       CancelableRequestMap;
148 
149   // Only call this when you already have acquired pending_request_lock_.
150   void CancelRequestLocked(const CancelableRequestMap::iterator& item);
151 
152   friend class CancelableRequestBase;
153 
154   base::Lock pending_request_lock_;
155 
156   // Lists all outstanding requests. Protected by the |lock_|.
157   CancelableRequestMap pending_requests_;
158 
159   // The next handle value we will return. Protected by the |lock_|.
160   int next_handle_;
161 
162   DISALLOW_COPY_AND_ASSIGN(CancelableRequestProvider);
163 };
164 
165 // CancelableRequestConsumer --------------------------------------------------
166 //
167 // Classes wishing to make requests on a provider should have an instance of
168 // this class. Callers will need to pass a pointer to this consumer object
169 // when they make the request. It will automatically track any pending
170 // requests, and will automatically cancel them on destruction to prevent the
171 // accidental calling of freed memory.
172 //
173 // It is recommended to just have this class as a member variable since there
174 // is nothing to be gained by inheriting from it other than polluting your
175 // namespace.
176 //
177 // THIS CLASS IS NOT THREADSAFE (unlike the provider). You must make requests
178 // and get callbacks all from the same thread.
179 
180 // Base class used to notify of new requests.
181 class CancelableRequestConsumerBase {
182  protected:
183   friend class CancelableRequestBase;
184   friend class CancelableRequestProvider;
185 
~CancelableRequestConsumerBase()186   virtual ~CancelableRequestConsumerBase() {
187   }
188 
189   // Adds a new request to the list of requests that are being tracked. This
190   // is called by the provider when a new request is created.
191   virtual void OnRequestAdded(CancelableRequestProvider* provider,
192                               CancelableRequestProvider::Handle handle) = 0;
193 
194   // Removes the given request from the list of pending requests. Called
195   // by the CancelableRequest immediately after the callback has executed for a
196   // given request, and by the provider when a request is canceled.
197   virtual void OnRequestRemoved(CancelableRequestProvider* provider,
198                                 CancelableRequestProvider::Handle handle) = 0;
199 
200   // Sent to provider before executing a callback.
201   virtual void WillExecute(CancelableRequestProvider* provider,
202                            CancelableRequestProvider::Handle handle) = 0;
203 
204   // Sent after executing a callback.
205   virtual void DidExecute(CancelableRequestProvider* provider,
206                           CancelableRequestProvider::Handle handle) = 0;
207 };
208 
209 // Template for clients to use. It allows them to associate random "client
210 // data" with a specific request. The default value for this type is 0.
211 // The type T should be small and easily copyable (like a pointer
212 // or an integer).
213 template<class T>
214 class CancelableRequestConsumerTSimple
215     : public CancelableRequestConsumerBase {
216  public:
217   CancelableRequestConsumerTSimple();
218 
219   // Cancel any outstanding requests so that we do not get called back after we
220   // are destroyed. As these requests are removed, the providers will call us
221   // back on OnRequestRemoved, which will then update the list. To iterate
222   // successfully while the list is changing out from under us, we make a copy.
223   virtual ~CancelableRequestConsumerTSimple();
224 
225   // Associates some random data with a specified request. The request MUST be
226   // outstanding, or it will assert. This is intended to be called immediately
227   // after a request is issued.
228   void SetClientData(CancelableRequestProvider* p,
229                      CancelableRequestProvider::Handle h,
230                      T client_data);
231 
232   // Retrieves previously associated data for a specified request. The request
233   // MUST be outstanding, or it will assert. This is intended to be called
234   // during processing of a callback to retrieve extra data.
235   T GetClientData(CancelableRequestProvider* p,
236                   CancelableRequestProvider::Handle h);
237 
238   // Returns the data associated with the current request being processed. This
239   // is only valid during the time a callback is being processed.
240   T GetClientDataForCurrentRequest();
241 
242   // Returns true if there are any pending requests.
243   bool HasPendingRequests() const;
244 
245   // Returns the number of pending requests.
246   size_t PendingRequestCount() const;
247 
248   // Cancels all requests outstanding.
249   void CancelAllRequests();
250 
251   // Cancels all requests outstanding matching the client data.
252   void CancelAllRequestsForClientData(T client_data);
253 
254   // Returns the handle for the first request that has the specified client data
255   // (in |handle|). Returns true if there is a request for the specified client
256   // data, false otherwise.
257   bool GetFirstHandleForClientData(T client_data,
258                                    CancelableRequestProvider::Handle* handle);
259 
260   // Gets the client data for all pending requests.
261   void GetAllClientData(std::vector<T>* data);
262 
263  protected:
264   struct PendingRequest {
PendingRequestPendingRequest265     PendingRequest(CancelableRequestProvider* p,
266                    CancelableRequestProvider::Handle h)
267         : provider(p), handle(h) {
268     }
269 
PendingRequestPendingRequest270     PendingRequest() : provider(NULL), handle(0) {}
271 
272     // Comparison operator for stl.
273     bool operator<(const PendingRequest& other) const {
274       if (provider != other.provider)
275         return provider < other.provider;
276       return handle < other.handle;
277     }
278 
is_validPendingRequest279     bool is_valid() const { return provider != NULL; }
280 
281     CancelableRequestProvider* provider;
282     CancelableRequestProvider::Handle handle;
283   };
284   typedef std::map<PendingRequest, T> PendingRequestList;
285 
286   virtual T get_initial_t() const;
287 
288   virtual void OnRequestAdded(CancelableRequestProvider* provider,
289                               CancelableRequestProvider::Handle handle);
290 
291   virtual void OnRequestRemoved(CancelableRequestProvider* provider,
292                                 CancelableRequestProvider::Handle handle);
293 
294   virtual void WillExecute(CancelableRequestProvider* provider,
295                            CancelableRequestProvider::Handle handle);
296 
297   virtual void DidExecute(CancelableRequestProvider* provider,
298                           CancelableRequestProvider::Handle handle);
299 
300   // Lists all outstanding requests.
301   PendingRequestList pending_requests_;
302 
303   // This is valid while processing a request and is used to identify the
304   // provider/handle of request.
305   PendingRequest current_request_;
306 };
307 
308 template<class T>
CancelableRequestConsumerTSimple()309 CancelableRequestConsumerTSimple<T>::CancelableRequestConsumerTSimple() {
310 }
311 
312 template<class T>
~CancelableRequestConsumerTSimple()313 CancelableRequestConsumerTSimple<T>::~CancelableRequestConsumerTSimple() {
314   CancelAllRequests();
315 }
316 
317 template<class T>
SetClientData(CancelableRequestProvider * p,CancelableRequestProvider::Handle h,T client_data)318 void CancelableRequestConsumerTSimple<T>::SetClientData(
319     CancelableRequestProvider* p,
320     CancelableRequestProvider::Handle h,
321     T client_data) {
322   PendingRequest request(p, h);
323   DCHECK(pending_requests_.find(request) != pending_requests_.end());
324   pending_requests_[request] = client_data;
325 }
326 
327 template<class T>
GetClientData(CancelableRequestProvider * p,CancelableRequestProvider::Handle h)328 T CancelableRequestConsumerTSimple<T>::GetClientData(
329     CancelableRequestProvider* p,
330     CancelableRequestProvider::Handle h) {
331   PendingRequest request(p, h);
332   DCHECK(pending_requests_.find(request) != pending_requests_.end());
333   return pending_requests_[request];
334 }
335 
336 template<class T>
GetClientDataForCurrentRequest()337 T CancelableRequestConsumerTSimple<T>::GetClientDataForCurrentRequest() {
338   DCHECK(current_request_.is_valid());
339   return GetClientData(current_request_.provider, current_request_.handle);
340 }
341 
342 template<class T>
HasPendingRequests()343 bool CancelableRequestConsumerTSimple<T>::HasPendingRequests() const {
344   return !pending_requests_.empty();
345 }
346 
347 template<class T>
PendingRequestCount()348 size_t CancelableRequestConsumerTSimple<T>::PendingRequestCount() const {
349   return pending_requests_.size();
350 }
351 
352 template<class T>
CancelAllRequests()353 void CancelableRequestConsumerTSimple<T>::CancelAllRequests() {
354   // TODO(atwilson): This code is not thread safe as it is called from the
355   // consumer thread (via the destructor) and accesses pending_requests_
356   // without acquiring the provider lock (http://crbug.com/85970).
357   PendingRequestList copied_requests(pending_requests_);
358   for (typename PendingRequestList::iterator i = copied_requests.begin();
359        i != copied_requests.end(); ++i) {
360     i->first.provider->CancelRequest(i->first.handle);
361   }
362   copied_requests.clear();
363 
364   // That should have cleared all the pending items.
365   DCHECK(pending_requests_.empty());
366 }
367 
368 template<class T>
CancelAllRequestsForClientData(T client_data)369 void CancelableRequestConsumerTSimple<T>::CancelAllRequestsForClientData(
370     T client_data) {
371   PendingRequestList copied_requests(pending_requests_);
372   for (typename PendingRequestList::const_iterator i = copied_requests.begin();
373       i != copied_requests.end(); ++i) {
374     if (i->second == client_data)
375       i->first.provider->CancelRequest(i->first.handle);
376   }
377   copied_requests.clear();
378 }
379 
380 template<class T>
GetFirstHandleForClientData(T client_data,CancelableRequestProvider::Handle * handle)381 bool CancelableRequestConsumerTSimple<T>::GetFirstHandleForClientData(
382     T client_data,
383     CancelableRequestProvider::Handle* handle) {
384   for (typename PendingRequestList::const_iterator i =
385            pending_requests_.begin(); i != pending_requests_.end(); ++i) {
386     if (i->second == client_data) {
387       *handle = i->first.handle;
388       return true;
389     }
390   }
391   *handle = 0;
392   return false;
393 }
394 
395 template<class T>
GetAllClientData(std::vector<T> * data)396 void CancelableRequestConsumerTSimple<T>::GetAllClientData(
397     std::vector<T>* data) {
398   DCHECK(data);
399   for (typename PendingRequestList::iterator i = pending_requests_.begin();
400        i != pending_requests_.end(); ++i)
401     data->push_back(i->second);
402 }
403 
404 template<class T>
get_initial_t()405 T CancelableRequestConsumerTSimple<T>::get_initial_t() const {
406   return T();
407 }
408 
409 template<class T>
OnRequestAdded(CancelableRequestProvider * provider,CancelableRequestProvider::Handle handle)410 void CancelableRequestConsumerTSimple<T>::OnRequestAdded(
411     CancelableRequestProvider* provider,
412     CancelableRequestProvider::Handle handle) {
413   // Make sure we're not mixing/matching providers (since the provider is
414   // responsible for providing thread safety until http://crbug.com/85970 is
415   // fixed, we can't use the same consumer with multiple providers).
416 #ifndef NDEBUG
417   if (!pending_requests_.empty())
418     DCHECK(pending_requests_.begin()->first.provider == provider);
419 #endif
420   DCHECK(pending_requests_.find(PendingRequest(provider, handle)) ==
421          pending_requests_.end());
422   pending_requests_[PendingRequest(provider, handle)] = get_initial_t();
423 }
424 
425 template<class T>
OnRequestRemoved(CancelableRequestProvider * provider,CancelableRequestProvider::Handle handle)426 void CancelableRequestConsumerTSimple<T>::OnRequestRemoved(
427     CancelableRequestProvider* provider,
428     CancelableRequestProvider::Handle handle) {
429   typename PendingRequestList::iterator i =
430       pending_requests_.find(PendingRequest(provider, handle));
431   if (i == pending_requests_.end()) {
432     NOTREACHED() << "Got a complete notification for a nonexistent request";
433     return;
434   }
435 
436   pending_requests_.erase(i);
437 }
438 
439 template<class T>
WillExecute(CancelableRequestProvider * provider,CancelableRequestProvider::Handle handle)440 void CancelableRequestConsumerTSimple<T>::WillExecute(
441     CancelableRequestProvider* provider,
442     CancelableRequestProvider::Handle handle) {
443   current_request_ = PendingRequest(provider, handle);
444 }
445 
446 template<class T>
DidExecute(CancelableRequestProvider * provider,CancelableRequestProvider::Handle handle)447 void CancelableRequestConsumerTSimple<T>::DidExecute(
448     CancelableRequestProvider* provider,
449     CancelableRequestProvider::Handle handle) {
450   current_request_ = PendingRequest();
451 }
452 
453 // See CancelableRequestConsumerTSimple. The default value for T
454 // is given in |initial_t|.
455 template<class T, T initial_t>
456 class CancelableRequestConsumerT
457     : public CancelableRequestConsumerTSimple<T> {
458  public:
459   CancelableRequestConsumerT();
460   virtual ~CancelableRequestConsumerT();
461 
462  protected:
463   virtual T get_initial_t() const;
464 };
465 
466 template<class T, T initial_t>
CancelableRequestConsumerT()467 CancelableRequestConsumerT<T, initial_t>::CancelableRequestConsumerT() {
468 }
469 
470 template<class T, T initial_t>
~CancelableRequestConsumerT()471 CancelableRequestConsumerT<T, initial_t>::~CancelableRequestConsumerT() {
472 }
473 
474 template<class T, T initial_t>
get_initial_t()475 T CancelableRequestConsumerT<T, initial_t>::get_initial_t() const {
476   return initial_t;
477 }
478 
479 // Some clients may not want to store data. Rather than do some complicated
480 // thing with virtual functions to allow some consumers to store extra data and
481 // some not to, we just define a default one that stores some dummy data.
482 typedef CancelableRequestConsumerT<int, 0> CancelableRequestConsumer;
483 
484 // MSVC doesn't like complex extern templates and DLLs.
485 #if !defined(COMPILER_MSVC)
486 // The vast majority of CancelableRequestConsumers are instantiated on <int>,
487 // so prevent that template from being expanded in normal code.
488 extern template class CancelableRequestConsumerTSimple<int>;
489 
490 // We'll also want to extern-template the most common, typedef-ed
491 // CancelableRequestConsumerT.
492 extern template class CancelableRequestConsumerT<int, 0>;
493 #endif
494 
495 // CancelableRequest ----------------------------------------------------------
496 //
497 // The request object that is used by a CancelableRequestProvider to send
498 // results to a CancelableRequestConsumer. This request handles the returning
499 // of results from a thread where the request is being executed to the thread
500 // and callback where the results are used. IT SHOULD BE PASSED AS A
501 // scoped_refptr TO KEEP IT ALIVE.
502 //
503 // It does not handle input parameters to the request. The caller must either
504 // transfer those separately or derive from this class to add the desired
505 // parameters.
506 //
507 // When the processing is complete on this message, the caller MUST call
508 // ForwardResult() with the return arguments that will be passed to the
509 // callback. If the request has been canceled, Return is optional (it will not
510 // do anything). If you do not have to return to the caller, the cancelable
511 // request system should not be used! (just use regular fire-and-forget tasks).
512 //
513 // Callback parameters are passed by value. In some cases, the request will
514 // want to return a large amount of data (for example, an image). One good
515 // approach is to derive from the CancelableRequest and make the data object
516 // (for example, a std::vector) owned by the CancelableRequest. The pointer
517 // to this data would be passed for the callback parameter. Since the
518 // CancelableRequest outlives the callback call, the data will be valid on the
519 // other thread for the callback, but will still be destroyed properly.
520 
521 // Non-templatized base class that provides cancellation
522 class CancelableRequestBase
523     : public base::RefCountedThreadSafe<CancelableRequestBase> {
524  public:
525   friend class CancelableRequestProvider;
526 
527   // Initializes most things to empty, Init() must be called to complete
528   // initialization of the object. This will be done by the provider when the
529   // request is dispatched.
530   //
531   // This must be called on the same thread the callback will be executed on, it
532   // will save that thread for later.
533   //
534   // This two-phase init is done so that the constructor can have no parameters,
535   // which makes it much more convenient for derived classes, which can be
536   // common. The derived classes need only declare the variables they provide in
537   // the constructor rather than many lines of internal tracking data that are
538   // passed to the base class (us).
539   //
540   // In addition, not all of the information (for example, the handle) is known
541   // at construction time.
542   CancelableRequestBase();
543 
consumer()544   CancelableRequestConsumerBase* consumer() const {
545     return consumer_;
546   }
547 
handle()548   CancelableRequestProvider::Handle handle() const {
549     return handle_;
550   }
551 
552   // The canceled flag indicates that the request should not be executed.
553   // A request can never be uncanceled, so only a setter for true is provided.
554   // This can be called multiple times, but only from one thread.
set_canceled()555   void set_canceled() {
556     canceled_.Set();
557   }
canceled()558   bool canceled() {
559     return canceled_.IsSet();
560   }
561 
562  protected:
563   friend class base::RefCountedThreadSafe<CancelableRequestBase>;
564   virtual ~CancelableRequestBase();
565 
566   // Initializes the object with the particulars from the provider. It may only
567   // be called once (it is called by the provider, which is a friend).
568   void Init(CancelableRequestProvider* provider,
569             CancelableRequestProvider::Handle handle,
570             CancelableRequestConsumerBase* consumer);
571 
572   // Attempts to execute callback on |callback_thread_| if the request has not
573   // been canceled yet.
574   void DoForward(const base::Closure& forwarded_call, bool force_async);
575 
576   // Tells the provider that the request is complete, which then tells the
577   // consumer.
NotifyCompleted()578   void NotifyCompleted() const {
579     provider_->RequestCompleted(handle());
580     consumer_->DidExecute(provider_, handle_);
581   }
582 
583   // Cover method for CancelableRequestConsumerBase::WillExecute.
WillExecute()584   void WillExecute() {
585     consumer_->WillExecute(provider_, handle_);
586   }
587 
588   // The message loop that this request was created on. The callback will
589   // happen on the same thread.
590   base::MessageLoop* callback_thread_;
591 
592   // The provider for this request. When we execute, we will notify this that
593   // request is complete to it can remove us from the requests it tracks.
594   CancelableRequestProvider* provider_;
595 
596   // Notified after we execute that the request is complete.  This should only
597   // be accessed if !canceled_.IsSet(), otherwise the pointer is invalid.
598   CancelableRequestConsumerBase* consumer_;
599 
600   // The handle to this request inside the provider. This will be initialized
601   // to 0 when the request is created, and the provider will set it once the
602   // request has been dispatched.
603   CancelableRequestProvider::Handle handle_;
604 
605   // Set if the caller cancels this request. No callbacks should be made when
606   // this is set.
607   base::CancellationFlag canceled_;
608 
609  private:
610   // Executes the |forwarded_call| and notifies the provider and the consumer
611   // that this request has been completed. This must be called on the
612   // |callback_thread_|.
613   void ExecuteCallback(const base::Closure& forwarded_call);
614 
615   DISALLOW_COPY_AND_ASSIGN(CancelableRequestBase);
616 };
617 
618 // Templatized class. This is the one you should use directly or inherit from.
619 // The callback can be invoked by calling the ForwardResult() method. For this,
620 // you must either pack the parameters into a tuple, or use DispatchToMethod
621 // (in tuple.h).
622 //
623 // If you inherit to add additional input parameters or to do more complex
624 // memory management (see the bigger comment about this above), you can put
625 // those on a subclass of this.
626 //
627 // We have decided to allow users to treat derived classes of this as structs,
628 // so you can add members without getters and setters (which just makes the
629 // code harder to read). Don't use underscores after these vars. For example:
630 //
631 //   typedef Callback1<int>::Type DoodieCallback;
632 //
633 //   class DoodieRequest : public CancelableRequest<DoodieCallback> {
634 //    public:
635 //     DoodieRequest(CallbackType* callback) : CancelableRequest(callback) {
636 //     }
637 //
638 //    private:
639 //     ~DoodieRequest() {}
640 //
641 //     int input_arg1;
642 //     std::wstring input_arg2;
643 //   };
644 template<typename CB>
645 class CancelableRequest : public CancelableRequestBase {
646  public:
647   // TODO(ajwong): After all calls have been migrated, remove this template in
648   // favor of the specialization on base::Callback<Sig>.
649   typedef CB CallbackType;          // CallbackRunner<...>
650   typedef typename CB::TupleType TupleType;  // Tuple of the callback args.
651 
652   // The provider MUST call Init() (on the base class) before this is valid.
653   // This class will take ownership of the callback object and destroy it when
654   // appropriate.
CancelableRequest(CallbackType * callback)655   explicit CancelableRequest(CallbackType* callback)
656       : CancelableRequestBase(),
657         callback_(callback) {
658     DCHECK(callback) << "We should always have a callback";
659   }
660 
661   // Dispatches the parameters to the correct thread so the callback can be
662   // executed there. The caller does not need to check for cancel before
663   // calling this. It is optional in the cancelled case. In the non-cancelled
664   // case, this MUST be called.
665   //
666   // If there are any pointers in the parameters, they must live at least as
667   // long as the request so that it can be forwarded to the other thread.
668   // For complex objects, this would typically be done by having a derived
669   // request own the data itself.
ForwardResult(const TupleType & param)670   void ForwardResult(const TupleType& param) {
671     DCHECK(callback_.get());
672     if (!canceled()) {
673       if (callback_thread_ == base::MessageLoop::current()) {
674         // We can do synchronous callbacks when we're on the same thread.
675         ExecuteCallback(param);
676       } else {
677         callback_thread_->PostTask(
678             FROM_HERE,
679             base::Bind(&CancelableRequest<CB>::ExecuteCallback, this, param));
680       }
681     }
682   }
683 
684   // Like |ForwardResult| but this never does a synchronous callback.
ForwardResultAsync(const TupleType & param)685   void ForwardResultAsync(const TupleType& param) {
686     DCHECK(callback_.get());
687     if (!canceled()) {
688       callback_thread_->PostTask(
689           FROM_HERE,
690           base::Bind(&CancelableRequest<CB>::ExecuteCallback, this, param));
691     }
692   }
693 
694  protected:
~CancelableRequest()695   virtual ~CancelableRequest() {}
696 
697  private:
698   // Executes the callback and notifies the provider and the consumer that this
699   // request has been completed. This must be called on the callback_thread_.
ExecuteCallback(const TupleType & param)700   void ExecuteCallback(const TupleType& param) {
701     if (!canceled_.IsSet()) {
702       WillExecute();
703 
704       // Execute the callback.
705       callback_->RunWithParams(param);
706     }
707 
708     // Notify the provider that the request is complete. The provider will
709     // notify the consumer for us. Note that it is possible for the callback to
710     // cancel this request; we must check canceled again.
711     if (!canceled_.IsSet())
712       NotifyCompleted();
713   }
714 
715   // This should only be executed if !canceled_.IsSet(),
716   // otherwise the pointers may be invalid.
717   scoped_ptr<CallbackType> callback_;
718 };
719 
720 // CancelableRequest<> wraps a normal base::Callback<> for use in the
721 // CancelableRequest framework.
722 //
723 // When using this class, the provider MUST call Init() (on the base class)
724 // before this is valid.
725 //
726 // The two functions ForwardResult(), and ForwardResultAsync() are used to
727 // invoke the wrapped callback on the correct thread.  They are the same
728 // except that ForwardResult() will run the callback synchronously if
729 // we are already on the right thread.
730 //
731 // The caller does not need to check for cancel before calling ForwardResult()
732 // or ForwardResultAsync(). If the request has not been canceled, one of the
733 // these MUST be called.
734 //
735 // If there are any pointers in the parameters, they must live at least as
736 // long as the request so that it can be forwarded to the other thread.
737 // For complex objects, this would typically be done by having a derived
738 // request own the data itself.
739 //
740 // The following specializations handle different arities of base::Callbacks<>.
741 template<>
742 class CancelableRequest<base::Closure> : public CancelableRequestBase {
743  public:
744   typedef base::Closure CallbackType;
745 
CancelableRequest(const CallbackType & callback)746   explicit CancelableRequest(const CallbackType& callback)
747       : CancelableRequestBase(),
748         callback_(callback) {
749     DCHECK(!callback.is_null()) << "Callback must be initialized.";
750   }
751 
ForwardResult(void)752   void ForwardResult(void) {
753     if (canceled()) return;
754     DoForward(callback_, false);
755   }
756 
ForwardResultAsync()757   void ForwardResultAsync() {
758     if (canceled()) return;
759     DoForward(callback_, true);
760   }
761 
762  protected:
~CancelableRequest()763   virtual ~CancelableRequest() {}
764 
765  private:
766   CallbackType callback_;
767 };
768 
769 template<typename A1>
770 class CancelableRequest<base::Callback<void(A1)> >
771     : public CancelableRequestBase {
772  public:
773   typedef base::Callback<void(A1)> CallbackType;
774 
CancelableRequest(const CallbackType & callback)775   explicit CancelableRequest(const CallbackType& callback)
776       : CancelableRequestBase(),
777         callback_(callback) {
778     DCHECK(!callback.is_null()) << "Callback must be initialized.";
779   }
780 
ForwardResult(typename base::internal::CallbackParamTraits<A1>::ForwardType a1)781   void ForwardResult(
782       typename base::internal::CallbackParamTraits<A1>::ForwardType a1) {
783     if (canceled()) return;
784     DoForward(base::Bind(callback_, a1), false);
785   }
786 
ForwardResultAsync(typename base::internal::CallbackParamTraits<A1>::ForwardType a1)787   void ForwardResultAsync(
788       typename base::internal::CallbackParamTraits<A1>::ForwardType a1) {
789     if (canceled()) return;
790     DoForward(base::Bind(callback_, a1), true);
791   }
792 
793  protected:
~CancelableRequest()794   virtual ~CancelableRequest() {}
795 
796  private:
797   CallbackType callback_;
798 };
799 
800 template<typename A1, typename A2>
801 class CancelableRequest<base::Callback<void(A1,A2)> >
802     : public CancelableRequestBase {
803  public:
804   typedef base::Callback<void(A1,A2)> CallbackType;
805 
CancelableRequest(const CallbackType & callback)806   explicit CancelableRequest(const CallbackType& callback)
807       : CancelableRequestBase(),
808         callback_(callback) {
809     DCHECK(!callback.is_null()) << "Callback must be initialized.";
810   }
811 
ForwardResult(typename base::internal::CallbackParamTraits<A1>::ForwardType a1,typename base::internal::CallbackParamTraits<A2>::ForwardType a2)812   void ForwardResult(
813       typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
814       typename base::internal::CallbackParamTraits<A2>::ForwardType a2) {
815     if (canceled()) return;
816     DoForward(base::Bind(callback_, a1, a2), false);
817   }
818 
ForwardResultAsync(typename base::internal::CallbackParamTraits<A1>::ForwardType a1,typename base::internal::CallbackParamTraits<A2>::ForwardType a2)819   void ForwardResultAsync(
820       typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
821       typename base::internal::CallbackParamTraits<A2>::ForwardType a2) {
822     if (canceled()) return;
823     DoForward(base::Bind(callback_, a1, a2), true);
824   }
825 
826  protected:
~CancelableRequest()827   virtual ~CancelableRequest() {}
828 
829  private:
830   CallbackType callback_;
831 };
832 
833 template<typename A1, typename A2, typename A3>
834 class CancelableRequest<base::Callback<void(A1,A2,A3)> >
835     : public CancelableRequestBase {
836  public:
837   typedef base::Callback<void(A1,A2,A3)> CallbackType;
838 
CancelableRequest(const CallbackType & callback)839   explicit CancelableRequest(const CallbackType& callback)
840       : CancelableRequestBase(),
841         callback_(callback) {
842     DCHECK(!callback.is_null()) << "Callback must be initialized.";
843   }
844 
ForwardResult(typename base::internal::CallbackParamTraits<A1>::ForwardType a1,typename base::internal::CallbackParamTraits<A2>::ForwardType a2,typename base::internal::CallbackParamTraits<A3>::ForwardType a3)845   void ForwardResult(
846       typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
847       typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
848       typename base::internal::CallbackParamTraits<A3>::ForwardType a3) {
849     if (canceled()) return;
850     DoForward(base::Bind(callback_, a1, a2, a3), false);
851   }
852 
ForwardResultAsync(typename base::internal::CallbackParamTraits<A1>::ForwardType a1,typename base::internal::CallbackParamTraits<A2>::ForwardType a2,typename base::internal::CallbackParamTraits<A3>::ForwardType a3)853   void ForwardResultAsync(
854       typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
855       typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
856       typename base::internal::CallbackParamTraits<A3>::ForwardType a3) {
857     if (canceled()) return;
858     DoForward(base::Bind(callback_, a1, a2, a3), true);
859   }
860 
861  protected:
~CancelableRequest()862   virtual ~CancelableRequest() {}
863 
864  private:
865   CallbackType callback_;
866 };
867 
868 template<typename A1, typename A2, typename A3, typename A4>
869 class CancelableRequest<base::Callback<void(A1, A2, A3, A4)> >
870     : public CancelableRequestBase {
871  public:
872   typedef base::Callback<void(A1, A2, A3, A4)> CallbackType;
873 
CancelableRequest(const CallbackType & callback)874   explicit CancelableRequest(const CallbackType& callback)
875       : CancelableRequestBase(),
876         callback_(callback) {
877     DCHECK(!callback.is_null()) << "Callback must be initialized.";
878   }
879 
ForwardResult(typename base::internal::CallbackParamTraits<A1>::ForwardType a1,typename base::internal::CallbackParamTraits<A2>::ForwardType a2,typename base::internal::CallbackParamTraits<A3>::ForwardType a3,typename base::internal::CallbackParamTraits<A4>::ForwardType a4)880   void ForwardResult(
881       typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
882       typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
883       typename base::internal::CallbackParamTraits<A3>::ForwardType a3,
884       typename base::internal::CallbackParamTraits<A4>::ForwardType a4) {
885     if (canceled()) return;
886     DoForward(base::Bind(callback_, a1, a2, a3, a4), false);
887   }
888 
ForwardResultAsync(typename base::internal::CallbackParamTraits<A1>::ForwardType a1,typename base::internal::CallbackParamTraits<A2>::ForwardType a2,typename base::internal::CallbackParamTraits<A3>::ForwardType a3,typename base::internal::CallbackParamTraits<A4>::ForwardType a4)889   void ForwardResultAsync(
890       typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
891       typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
892       typename base::internal::CallbackParamTraits<A3>::ForwardType a3,
893       typename base::internal::CallbackParamTraits<A4>::ForwardType a4) {
894     if (canceled()) return;
895     DoForward(base::Bind(callback_, a1, a2, a3, a4), true);
896   }
897 
898  protected:
~CancelableRequest()899   virtual ~CancelableRequest() {}
900 
901  private:
902   CallbackType callback_;
903 };
904 
905 template<typename A1, typename A2, typename A3, typename A4, typename A5>
906 class CancelableRequest<base::Callback<void(A1, A2, A3, A4, A5)> >
907     : public CancelableRequestBase {
908  public:
909   typedef base::Callback<void(A1, A2, A3, A4, A5)> CallbackType;
910 
CancelableRequest(const CallbackType & callback)911   explicit CancelableRequest(const CallbackType& callback)
912       : CancelableRequestBase(),
913         callback_(callback) {
914     DCHECK(!callback.is_null()) << "Callback must be initialized.";
915   }
916 
ForwardResult(typename base::internal::CallbackParamTraits<A1>::ForwardType a1,typename base::internal::CallbackParamTraits<A2>::ForwardType a2,typename base::internal::CallbackParamTraits<A3>::ForwardType a3,typename base::internal::CallbackParamTraits<A4>::ForwardType a4,typename base::internal::CallbackParamTraits<A5>::ForwardType a5)917   void ForwardResult(
918       typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
919       typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
920       typename base::internal::CallbackParamTraits<A3>::ForwardType a3,
921       typename base::internal::CallbackParamTraits<A4>::ForwardType a4,
922       typename base::internal::CallbackParamTraits<A5>::ForwardType a5) {
923     if (canceled()) return;
924     DoForward(base::Bind(callback_, a1, a2, a3, a4, a5), false);
925   }
926 
ForwardResultAsync(typename base::internal::CallbackParamTraits<A1>::ForwardType a1,typename base::internal::CallbackParamTraits<A2>::ForwardType a2,typename base::internal::CallbackParamTraits<A3>::ForwardType a3,typename base::internal::CallbackParamTraits<A4>::ForwardType a4,typename base::internal::CallbackParamTraits<A5>::ForwardType a5)927   void ForwardResultAsync(
928       typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
929       typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
930       typename base::internal::CallbackParamTraits<A3>::ForwardType a3,
931       typename base::internal::CallbackParamTraits<A4>::ForwardType a4,
932       typename base::internal::CallbackParamTraits<A5>::ForwardType a5) {
933     if (canceled()) return;
934     DoForward(base::Bind(callback_, a1, a2, a3, a4, a5), true);
935   }
936 
937  protected:
~CancelableRequest()938   virtual ~CancelableRequest() {}
939 
940  private:
941   CallbackType callback_;
942 };
943 
944 template<typename A1, typename A2, typename A3, typename A4, typename A5,
945          typename A6>
946 class CancelableRequest<base::Callback<void(A1, A2, A3, A4, A5, A6)> >
947     : public CancelableRequestBase {
948  public:
949   typedef base::Callback<void(A1, A2, A3, A4, A5, A6)> CallbackType;
950 
CancelableRequest(const CallbackType & callback)951   explicit CancelableRequest(const CallbackType& callback)
952       : CancelableRequestBase(),
953         callback_(callback) {
954     DCHECK(!callback.is_null()) << "Callback must be initialized.";
955   }
956 
ForwardResult(typename base::internal::CallbackParamTraits<A1>::ForwardType a1,typename base::internal::CallbackParamTraits<A2>::ForwardType a2,typename base::internal::CallbackParamTraits<A3>::ForwardType a3,typename base::internal::CallbackParamTraits<A4>::ForwardType a4,typename base::internal::CallbackParamTraits<A5>::ForwardType a5,typename base::internal::CallbackParamTraits<A6>::ForwardType a6)957   void ForwardResult(
958       typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
959       typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
960       typename base::internal::CallbackParamTraits<A3>::ForwardType a3,
961       typename base::internal::CallbackParamTraits<A4>::ForwardType a4,
962       typename base::internal::CallbackParamTraits<A5>::ForwardType a5,
963       typename base::internal::CallbackParamTraits<A6>::ForwardType a6) {
964     if (canceled()) return;
965     DoForward(base::Bind(callback_, a1, a2, a3, a4, a5, a6), false);
966   }
967 
ForwardResultAsync(typename base::internal::CallbackParamTraits<A1>::ForwardType a1,typename base::internal::CallbackParamTraits<A2>::ForwardType a2,typename base::internal::CallbackParamTraits<A3>::ForwardType a3,typename base::internal::CallbackParamTraits<A4>::ForwardType a4,typename base::internal::CallbackParamTraits<A5>::ForwardType a5,typename base::internal::CallbackParamTraits<A6>::ForwardType a6)968   void ForwardResultAsync(
969       typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
970       typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
971       typename base::internal::CallbackParamTraits<A3>::ForwardType a3,
972       typename base::internal::CallbackParamTraits<A4>::ForwardType a4,
973       typename base::internal::CallbackParamTraits<A5>::ForwardType a5,
974       typename base::internal::CallbackParamTraits<A6>::ForwardType a6) {
975     if (canceled()) return;
976     DoForward(base::Bind(callback_, a1, a2, a3, a4, a5, a6), true);
977   }
978 
979  protected:
~CancelableRequest()980   virtual ~CancelableRequest() {}
981 
982  private:
983   CallbackType callback_;
984 };
985 
986 // A CancelableRequest with a single value. This is intended for use when
987 // the provider provides a single value. The provider fills the result into
988 // the value, and notifies the request with a pointer to the value. For example,
989 // HistoryService has many methods that callback with a vector. Use the
990 // following pattern for this:
991 // 1. Define the callback:
992 //      typedef Callback2<Handle, std::vector<Foo>*>::Type FooCallback;
993 // 2. Define the CancelableRequest1 type.
994 //    typedef CancelableRequest1<FooCallback, std::vector<Foo>> FooRequest;
995 // 3. The provider method should then fill in the contents of the vector,
996 //    forwarding the result like so:
997 //    request->ForwardResult(FooRequest::TupleType(request->handle(),
998 //                                                 &request->value));
999 //
1000 // Tip: for passing more than one value, use a Tuple for the value.
1001 template<typename CB, typename Type>
1002 class CancelableRequest1 : public CancelableRequest<CB> {
1003  public:
CancelableRequest1(const typename CancelableRequest<CB>::CallbackType & callback)1004   explicit CancelableRequest1(
1005       const typename CancelableRequest<CB>::CallbackType& callback)
1006       : CancelableRequest<CB>(callback), value() {
1007   }
1008 
1009   // The value.
1010   Type value;
1011 
1012  protected:
~CancelableRequest1()1013   virtual ~CancelableRequest1() {}
1014 };
1015 
1016 #endif  // CHROME_BROWSER_COMMON_CANCELABLE_REQUEST_H_
1017