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 106class CancelableRequestBase; 107class 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 118class 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. 181class CancelableRequestConsumerBase { 182 protected: 183 friend class CancelableRequestBase; 184 friend class CancelableRequestProvider; 185 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). 213template<class T> 214class 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 { 265 PendingRequest(CancelableRequestProvider* p, 266 CancelableRequestProvider::Handle h) 267 : provider(p), handle(h) { 268 } 269 270 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 279 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 308template<class T> 309CancelableRequestConsumerTSimple<T>::CancelableRequestConsumerTSimple() { 310} 311 312template<class T> 313CancelableRequestConsumerTSimple<T>::~CancelableRequestConsumerTSimple() { 314 CancelAllRequests(); 315} 316 317template<class T> 318void 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 327template<class T> 328T 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 336template<class T> 337T CancelableRequestConsumerTSimple<T>::GetClientDataForCurrentRequest() { 338 DCHECK(current_request_.is_valid()); 339 return GetClientData(current_request_.provider, current_request_.handle); 340} 341 342template<class T> 343bool CancelableRequestConsumerTSimple<T>::HasPendingRequests() const { 344 return !pending_requests_.empty(); 345} 346 347template<class T> 348size_t CancelableRequestConsumerTSimple<T>::PendingRequestCount() const { 349 return pending_requests_.size(); 350} 351 352template<class T> 353void 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 368template<class T> 369void 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 380template<class T> 381bool 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 395template<class T> 396void 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 404template<class T> 405T CancelableRequestConsumerTSimple<T>::get_initial_t() const { 406 return T(); 407} 408 409template<class T> 410void 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 425template<class T> 426void 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 439template<class T> 440void CancelableRequestConsumerTSimple<T>::WillExecute( 441 CancelableRequestProvider* provider, 442 CancelableRequestProvider::Handle handle) { 443 current_request_ = PendingRequest(provider, handle); 444} 445 446template<class T> 447void 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|. 455template<class T, T initial_t> 456class CancelableRequestConsumerT 457 : public CancelableRequestConsumerTSimple<T> { 458 public: 459 CancelableRequestConsumerT(); 460 virtual ~CancelableRequestConsumerT(); 461 462 protected: 463 virtual T get_initial_t() const; 464}; 465 466template<class T, T initial_t> 467CancelableRequestConsumerT<T, initial_t>::CancelableRequestConsumerT() { 468} 469 470template<class T, T initial_t> 471CancelableRequestConsumerT<T, initial_t>::~CancelableRequestConsumerT() { 472} 473 474template<class T, T initial_t> 475T 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. 482typedef 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. 488extern template class CancelableRequestConsumerTSimple<int>; 489 490// We'll also want to extern-template the most common, typedef-ed 491// CancelableRequestConsumerT. 492extern 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 522class 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 544 CancelableRequestConsumerBase* consumer() const { 545 return consumer_; 546 } 547 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. 555 void set_canceled() { 556 canceled_.Set(); 557 } 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. 578 void NotifyCompleted() const { 579 provider_->RequestCompleted(handle()); 580 consumer_->DidExecute(provider_, handle_); 581 } 582 583 // Cover method for CancelableRequestConsumerBase::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// }; 644template<typename CB> 645class 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. 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. 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. 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: 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_. 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<>. 741template<> 742class CancelableRequest<base::Closure> : public CancelableRequestBase { 743 public: 744 typedef base::Closure CallbackType; 745 746 explicit CancelableRequest(const CallbackType& callback) 747 : CancelableRequestBase(), 748 callback_(callback) { 749 DCHECK(!callback.is_null()) << "Callback must be initialized."; 750 } 751 752 void ForwardResult(void) { 753 if (canceled()) return; 754 DoForward(callback_, false); 755 } 756 757 void ForwardResultAsync() { 758 if (canceled()) return; 759 DoForward(callback_, true); 760 } 761 762 protected: 763 virtual ~CancelableRequest() {} 764 765 private: 766 CallbackType callback_; 767}; 768 769template<typename A1> 770class CancelableRequest<base::Callback<void(A1)> > 771 : public CancelableRequestBase { 772 public: 773 typedef base::Callback<void(A1)> CallbackType; 774 775 explicit CancelableRequest(const CallbackType& callback) 776 : CancelableRequestBase(), 777 callback_(callback) { 778 DCHECK(!callback.is_null()) << "Callback must be initialized."; 779 } 780 781 void ForwardResult( 782 typename base::internal::CallbackParamTraits<A1>::ForwardType a1) { 783 if (canceled()) return; 784 DoForward(base::Bind(callback_, a1), false); 785 } 786 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: 794 virtual ~CancelableRequest() {} 795 796 private: 797 CallbackType callback_; 798}; 799 800template<typename A1, typename A2> 801class CancelableRequest<base::Callback<void(A1,A2)> > 802 : public CancelableRequestBase { 803 public: 804 typedef base::Callback<void(A1,A2)> CallbackType; 805 806 explicit CancelableRequest(const CallbackType& callback) 807 : CancelableRequestBase(), 808 callback_(callback) { 809 DCHECK(!callback.is_null()) << "Callback must be initialized."; 810 } 811 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 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: 827 virtual ~CancelableRequest() {} 828 829 private: 830 CallbackType callback_; 831}; 832 833template<typename A1, typename A2, typename A3> 834class CancelableRequest<base::Callback<void(A1,A2,A3)> > 835 : public CancelableRequestBase { 836 public: 837 typedef base::Callback<void(A1,A2,A3)> CallbackType; 838 839 explicit CancelableRequest(const CallbackType& callback) 840 : CancelableRequestBase(), 841 callback_(callback) { 842 DCHECK(!callback.is_null()) << "Callback must be initialized."; 843 } 844 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 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: 862 virtual ~CancelableRequest() {} 863 864 private: 865 CallbackType callback_; 866}; 867 868template<typename A1, typename A2, typename A3, typename A4> 869class CancelableRequest<base::Callback<void(A1, A2, A3, A4)> > 870 : public CancelableRequestBase { 871 public: 872 typedef base::Callback<void(A1, A2, A3, A4)> CallbackType; 873 874 explicit CancelableRequest(const CallbackType& callback) 875 : CancelableRequestBase(), 876 callback_(callback) { 877 DCHECK(!callback.is_null()) << "Callback must be initialized."; 878 } 879 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 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: 899 virtual ~CancelableRequest() {} 900 901 private: 902 CallbackType callback_; 903}; 904 905template<typename A1, typename A2, typename A3, typename A4, typename A5> 906class 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 911 explicit CancelableRequest(const CallbackType& callback) 912 : CancelableRequestBase(), 913 callback_(callback) { 914 DCHECK(!callback.is_null()) << "Callback must be initialized."; 915 } 916 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 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: 938 virtual ~CancelableRequest() {} 939 940 private: 941 CallbackType callback_; 942}; 943 944template<typename A1, typename A2, typename A3, typename A4, typename A5, 945 typename A6> 946class 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 951 explicit CancelableRequest(const CallbackType& callback) 952 : CancelableRequestBase(), 953 callback_(callback) { 954 DCHECK(!callback.is_null()) << "Callback must be initialized."; 955 } 956 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 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: 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. 1001template<typename CB, typename Type> 1002class CancelableRequest1 : public CancelableRequest<CB> { 1003 public: 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: 1013 virtual ~CancelableRequest1() {} 1014}; 1015 1016#endif // CHROME_BROWSER_COMMON_CANCELABLE_REQUEST_H_ 1017