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