| OLD | NEW |
| (Empty) |
| 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_CANCELABLE_REQUEST_H_ | |
| 89 #define CHROME_BROWSER_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.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 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_ == 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_CANCELABLE_REQUEST_H_ | |
| OLD | NEW |