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 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 { 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 308 template<class T> 309 CancelableRequestConsumerTSimple<T>::CancelableRequestConsumerTSimple() { 310 } 311 312 template<class T> 313 CancelableRequestConsumerTSimple<T>::~CancelableRequestConsumerTSimple() { 314 CancelAllRequests(); 315 } 316 317 template<class T> 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> 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> 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> 343 bool CancelableRequestConsumerTSimple<T>::HasPendingRequests() const { 344 return !pending_requests_.empty(); 345 } 346 347 template<class T> 348 size_t CancelableRequestConsumerTSimple<T>::PendingRequestCount() const { 349 return pending_requests_.size(); 350 } 351 352 template<class T> 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> 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> 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> 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> 405 T CancelableRequestConsumerTSimple<T>::get_initial_t() const { 406 return T(); 407 } 408 409 template<class T> 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> 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> 440 void CancelableRequestConsumerTSimple<T>::WillExecute( 441 CancelableRequestProvider* provider, 442 CancelableRequestProvider::Handle handle) { 443 current_request_ = PendingRequest(provider, handle); 444 } 445 446 template<class T> 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> 467 CancelableRequestConsumerT<T, initial_t>::CancelableRequestConsumerT() { 468 } 469 470 template<class T, T initial_t> 471 CancelableRequestConsumerT<T, initial_t>::~CancelableRequestConsumerT() { 472 } 473 474 template<class T, T 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 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 // }; 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. 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<>. 741 template<> 742 class 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 769 template<typename A1> 770 class 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 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 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 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 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 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 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 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 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 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 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. 1001 template<typename CB, typename Type> 1002 class 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