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 #ifndef PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_ 6 #define PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_ 7 8 #include "ppapi/cpp/completion_callback.h" 9 #include "ppapi/utility/completion_callback_factory_thread_traits.h" 10 11 /// @file 12 /// This file defines the API to create CompletionCallback objects that are 13 /// bound to member functions. 14 namespace pp { 15 16 // TypeUnwrapper -------------------------------------------------------------- 17 18 namespace internal { 19 20 // The TypeUnwrapper converts references and const references to the 21 // underlying type used for storage and passing as an argument. It is for 22 // internal use only. 23 template <typename T> struct TypeUnwrapper { 24 typedef T StorageType; 25 }; 26 template <typename T> struct TypeUnwrapper<T&> { 27 typedef T StorageType; 28 }; 29 template <typename T> struct TypeUnwrapper<const T&> { 30 typedef T StorageType; 31 }; 32 33 } // namespace internal 34 35 // ---------------------------------------------------------------------------- 36 37 /// CompletionCallbackFactory<T> may be used to create CompletionCallback 38 /// objects that are bound to member functions. 39 /// 40 /// If a factory is destroyed, then any pending callbacks will be cancelled 41 /// preventing any bound member functions from being called. The CancelAll() 42 /// method allows pending callbacks to be cancelled without destroying the 43 /// factory. 44 /// 45 /// <strong>Note: </strong><code>CompletionCallbackFactory<T></code> isn't 46 /// thread safe, but it is somewhat thread-friendly when used with a 47 /// thread-safe traits class as the second template element. However, it 48 /// only guarantees safety for creating a callback from another thread, the 49 /// callback itself needs to execute on the same thread as the thread that 50 /// creates/destroys the factory. With this restriction, it is safe to create 51 /// the <code>CompletionCallbackFactory</code> on the main thread, create 52 /// callbacks from any thread and pass them to CallOnMainThread(). 53 /// 54 /// <strong>Example: </strong> 55 /// 56 /// @code 57 /// class MyClass { 58 /// public: 59 /// // If an compiler warns on following using |this| in the initializer 60 /// // list, use PP_ALLOW_THIS_IN_INITIALIZER_LIST macro. 61 /// MyClass() : factory_(this) { 62 /// } 63 /// 64 /// void OpenFile(const pp::FileRef& file) { 65 /// pp::CompletionCallback cc = factory_.NewCallback(&MyClass::DidOpen); 66 /// int32_t rv = file_io_.Open(file, PP_FileOpenFlag_Read, cc); 67 /// CHECK(rv == PP_OK_COMPLETIONPENDING); 68 /// } 69 /// 70 /// private: 71 /// void DidOpen(int32_t result) { 72 /// if (result == PP_OK) { 73 /// // The file is open, and we can begin reading. 74 /// // ... 75 /// } else { 76 /// // Failed to open the file with error given by 'result'. 77 /// } 78 /// } 79 /// 80 /// pp::CompletionCallbackFactory<MyClass> factory_; 81 /// }; 82 /// @endcode 83 /// 84 /// <strong>Passing additional parameters to your callback</strong> 85 /// 86 /// As a convenience, the <code>CompletionCallbackFactory</code> can optionally 87 /// create a closure with up to three bound parameters that it will pass to 88 /// your callback function. This can be useful for passing information about 89 /// the request to your callback function, which is especially useful if your 90 /// class has multiple asynchronous callbacks pending. 91 /// 92 /// For the above example, of opening a file, let's say you want to keep some 93 /// description associated with your request, you might implement your OpenFile 94 /// and DidOpen callback as follows: 95 /// 96 /// @code 97 /// void OpenFile(const pp::FileRef& file) { 98 /// std::string message = "Opening file!"; 99 /// pp::CompletionCallback cc = factory_.NewCallback(&MyClass::DidOpen, 100 /// message); 101 /// int32_t rv = file_io_.Open(file, PP_FileOpenFlag_Read, cc); 102 /// CHECK(rv == PP_OK_COMPLETIONPENDING); 103 /// } 104 /// void DidOpen(int32_t result, const std::string& message) { 105 /// // "message" will be "Opening file!". 106 /// ... 107 /// } 108 /// @endcode 109 /// 110 /// <strong>Optional versus required callbacks</strong> 111 /// 112 /// When you create an "optional" callback, the browser may return the results 113 /// synchronously if they are available. This can allow for higher performance 114 /// in some cases if data is available quickly (for example, for network loads 115 /// where there may be a lot of data coming quickly). In this case, the 116 /// callback will never be run. 117 /// 118 /// When creating a new callback with the factory, there will be data allocated 119 /// on the heap that tracks the callback information and any bound arguments. 120 /// This data is freed when the callback executes. In the case of optional 121 /// callbacks, since the browser will never issue the callback, the internal 122 /// tracking data will be leaked. 123 /// 124 /// Therefore, if you use optional callbacks, it's important to manually 125 /// issue the callback to free up this data. The typical pattern is: 126 /// 127 /// @code 128 /// pp::CompletionCallback callback = callback_factory.NewOptionalCallback( 129 /// &MyClass::OnDataReady); 130 /// int32_t result = interface->GetData(callback); 131 /// if (result != PP_OK_COMPLETIONPENDING) 132 /// callback.Run(result); 133 /// @endcode 134 /// 135 /// Because of this additional complexity, it's generally recommended that 136 /// you not use optional callbacks except when performance is more important 137 /// (such as loading large resources from the network). In most other cases, 138 /// the performance difference will not be worth the additional complexity, 139 /// and most functions may never actually have the ability to complete 140 /// synchronously. 141 /// 142 /// <strong>Completion callbacks with output</strong> 143 /// 144 /// For some API calls, the browser returns data to the caller via an output 145 /// parameter. These can be difficult to manage since the output parameter 146 /// must remain valid for as long as the callback is pending. Note also that 147 /// CancelAll (or destroying the callback factory) does <i>not</i> cancel the 148 /// callback from the browser's perspective, only the execution of the callback 149 /// in the plugin code, and the output parameter will still be written to! 150 /// This means that you can't use class members as output parameters without 151 /// risking crashes. 152 /// 153 /// To make this case easier, the CompletionCallbackFactory can allocate and 154 /// manage the output data for you and pass it to your callback function. This 155 /// makes such calls more natural and less error-prone. 156 /// 157 /// To create such a callback, use NewCallbackWithOutput and specify a callback 158 /// function that takes the output parameter as its second argument. Let's say 159 /// you're calling a function GetFile which asynchronously returns a 160 /// pp::FileRef. GetFile's signature will be <code>int32_t GetFile(const 161 /// CompletionCallbackWithOutput<pp::FileRef>& callback);</code> and your 162 /// calling code would look like this: 163 /// 164 /// @code 165 /// void RequestFile() { 166 /// file_interface->GetFile(callback_factory_.NewCallbackWithOutput( 167 /// &MyClass::GotFile)); 168 /// } 169 /// void GotFile(int32_t result, const pp::FileRef& file) { 170 /// if (result == PP_OK) { 171 /// ...use file... 172 /// } else { 173 /// ...handle error... 174 /// } 175 /// } 176 /// @endcode 177 /// 178 /// As with regular completion callbacks, you can optionally add up to three 179 /// bound arguments. These are passed following the output argument. 180 /// 181 /// Your callback may take the output argument as a copy (common for small 182 /// types like integers, a const reference (common for structures and 183 /// resources to avoid an extra copy), or as a non-const reference. One 184 /// optimization you can do if your callback function may take large arrays 185 /// is to accept your output argument as a non-const reference and to swap() 186 /// the argument with a vector of your own to store it. This means you don't 187 /// have to copy the buffer to consume it. 188 /// 189 /// NewExtCallbackWithOutput is similar to NewCallbackWithOutput. It creates 190 /// ext::ExtCompletionCallbackWithOutput instances which are used by APIs within 191 /// the pp::ext namespace. 192 template <typename T, typename ThreadTraits = ThreadSafeThreadTraits> 193 class CompletionCallbackFactory { 194 public: 195 196 /// This constructor creates a <code>CompletionCallbackFactory</code> 197 /// bound to an object. If the constructor is called without an argument, 198 /// the default value of <code>NULL</code> is used. The user then must call 199 /// Initialize() to initialize the object. 200 /// 201 /// param[in] object Optional parameter. An object whose member functions 202 /// are to be bound to CompletionCallbacks created by this 203 /// <code>CompletionCallbackFactory</code>. The default value of this 204 /// parameter is <code>NULL</code>. 205 explicit CompletionCallbackFactory(T* object = NULL) 206 : object_(object) { 207 // Assume that we don't need to lock since construction should be complete 208 // before the pointer is used on another thread. 209 InitBackPointer(); 210 } 211 212 /// Destructor. 213 ~CompletionCallbackFactory() { 214 // Assume that we don't need to lock since this object should not be used 215 // from multiple threads during destruction. 216 ResetBackPointer(); 217 } 218 219 /// CancelAll() cancels all <code>CompletionCallbacks</code> allocated from 220 /// this factory. 221 void CancelAll() { 222 typename ThreadTraits::AutoLock lock(lock_); 223 224 ResetBackPointer(); 225 InitBackPointer(); 226 } 227 228 /// Initialize() binds the <code>CallbackFactory</code> to a particular 229 /// object. Use this when the object is not available at 230 /// <code>CallbackFactory</code> creation, and the <code>NULL</code> default 231 /// is passed to the constructor. The object may only be initialized once, 232 /// either by the constructor, or by a call to Initialize(). 233 /// 234 /// This class may not be used on any thread until initialization is complete. 235 /// 236 /// @param[in] object The object whose member functions are to be bound to 237 /// the <code>CompletionCallback</code> created by this 238 /// <code>CompletionCallbackFactory</code>. 239 void Initialize(T* object) { 240 PP_DCHECK(object); 241 PP_DCHECK(!object_); // May only initialize once! 242 object_ = object; 243 } 244 245 /// GetObject() returns the object that was passed at initialization to 246 /// Intialize(). 247 /// 248 /// @return the object passed to the constructor or Intialize(). 249 T* GetObject() { 250 return object_; 251 } 252 253 /// NewCallback allocates a new, single-use <code>CompletionCallback</code>. 254 /// The <code>CompletionCallback</code> must be run in order for the memory 255 /// allocated by the methods to be freed. 256 /// 257 /// @param[in] method The method to be invoked upon completion of the 258 /// operation. 259 /// 260 /// @return A <code>CompletionCallback</code>. 261 template <typename Method> 262 CompletionCallback NewCallback(Method method) { 263 return NewCallbackHelper(new Dispatcher0<Method>(method)); 264 } 265 266 /// NewOptionalCallback() allocates a new, single-use 267 /// <code>CompletionCallback</code> that might not run if the method 268 /// taking it can complete synchronously. Thus, if after passing the 269 /// CompletionCallback to a Pepper method, the method does not return 270 /// PP_OK_COMPLETIONPENDING, then you should manually call the 271 /// CompletionCallback's Run method, or memory will be leaked. 272 /// 273 /// @param[in] method The method to be invoked upon completion of the 274 /// operation. 275 /// 276 /// @return A <code>CompletionCallback</code>. 277 template <typename Method> 278 CompletionCallback NewOptionalCallback(Method method) { 279 CompletionCallback cc = NewCallback(method); 280 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); 281 return cc; 282 } 283 284 /// NewCallbackWithOutput() allocates a new, single-use 285 /// <code>CompletionCallback</code> where the browser will pass an additional 286 /// parameter containing the result of the request. The 287 /// <code>CompletionCallback</code> must be run in order for the memory 288 /// allocated by the methods to be freed. 289 /// 290 /// @param[in] method The method to be invoked upon completion of the 291 /// operation. 292 /// 293 /// @return A <code>CompletionCallback</code>. 294 template <typename Output> 295 CompletionCallbackWithOutput< 296 typename internal::TypeUnwrapper<Output>::StorageType> 297 NewCallbackWithOutput(void (T::*method)(int32_t, Output)) { 298 typedef typename internal::TypeUnwrapper<Output>::StorageType 299 OutputStorageType; 300 typedef CompletionCallbackWithOutput<OutputStorageType> CallbackType; 301 typedef DispatcherWithOutput0< 302 typename CallbackType::TraitsType, 303 OutputStorageType, 304 void (T::*)(int32_t, Output)> DispatcherType; 305 return NewCallbackWithOutputHelper<CallbackType>( 306 new DispatcherType(method)); 307 } 308 309 /// Similar to NewCallbackWithOutput(), but returns an 310 /// <code>ext::ExtCompletionCallbackWithOutput</code>. 311 template <typename Output> 312 ext::ExtCompletionCallbackWithOutput< 313 typename internal::TypeUnwrapper<Output>::StorageType> 314 NewExtCallbackWithOutput(void (T::*method)(int32_t, Output)) { 315 typedef typename internal::TypeUnwrapper<Output>::StorageType 316 OutputStorageType; 317 typedef ext::ExtCompletionCallbackWithOutput<OutputStorageType> 318 CallbackType; 319 typedef DispatcherWithOutput0< 320 typename CallbackType::TraitsType, 321 OutputStorageType, 322 void (T::*)(int32_t, Output)> DispatcherType; 323 return NewCallbackWithOutputHelper<CallbackType>( 324 new DispatcherType(method)); 325 } 326 327 /// NewCallback() allocates a new, single-use <code>CompletionCallback</code>. 328 /// The <code>CompletionCallback</code> must be run in order for the memory 329 /// allocated by the methods to be freed. 330 /// 331 /// @param[in] method The method to be invoked upon completion of the 332 /// operation. Method should be of type: 333 /// <code>void (T::*)(int32_t result, const A& a)</code> 334 /// 335 /// @param[in] a Passed to <code>method</code> when the completion callback 336 /// runs. 337 /// 338 /// @return A <code>CompletionCallback</code>. 339 template <typename Method, typename A> 340 CompletionCallback NewCallback(Method method, const A& a) { 341 return NewCallbackHelper(new Dispatcher1<Method, A>(method, a)); 342 } 343 344 /// NewOptionalCallback() allocates a new, single-use 345 /// <code>CompletionCallback</code> that might not run if the method 346 /// taking it can complete synchronously. Thus, if after passing the 347 /// CompletionCallback to a Pepper method, the method does not return 348 /// PP_OK_COMPLETIONPENDING, then you should manually call the 349 /// CompletionCallback's Run method, or memory will be leaked. 350 /// 351 /// @param[in] method The method to be invoked upon completion of the 352 /// operation. Method should be of type: 353 /// <code>void (T::*)(int32_t result, const A& a)</code> 354 /// 355 /// @param[in] a Passed to <code>method</code> when the completion callback 356 /// runs. 357 /// 358 /// @return A <code>CompletionCallback</code>. 359 template <typename Method, typename A> 360 CompletionCallback NewOptionalCallback(Method method, const A& a) { 361 CompletionCallback cc = NewCallback(method, a); 362 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); 363 return cc; 364 } 365 366 /// NewCallbackWithOutput() allocates a new, single-use 367 /// <code>CompletionCallback</code> where the browser will pass an additional 368 /// parameter containing the result of the request. The 369 /// <code>CompletionCallback</code> must be run in order for the memory 370 /// allocated by the methods to be freed. 371 /// 372 /// @param[in] method The method to be invoked upon completion of the 373 /// operation. 374 /// 375 /// @param[in] a Passed to <code>method</code> when the completion callback 376 /// runs. 377 /// 378 /// @return A <code>CompletionCallback</code>. 379 template <typename Output, typename A> 380 CompletionCallbackWithOutput< 381 typename internal::TypeUnwrapper<Output>::StorageType> 382 NewCallbackWithOutput(void (T::*method)(int32_t, Output, A), 383 const A& a) { 384 typedef typename internal::TypeUnwrapper<Output>::StorageType 385 OutputStorageType; 386 typedef CompletionCallbackWithOutput<OutputStorageType> CallbackType; 387 typedef DispatcherWithOutput1< 388 typename CallbackType::TraitsType, 389 OutputStorageType, 390 void (T::*)(int32_t, Output, A), 391 typename internal::TypeUnwrapper<A>::StorageType> DispatcherType; 392 return NewCallbackWithOutputHelper<CallbackType>( 393 new DispatcherType(method, a)); 394 } 395 396 /// Similar to NewCallbackWithOutput(), but returns an 397 /// <code>ext::ExtCompletionCallbackWithOutput</code>. 398 template <typename Output, typename A> 399 ext::ExtCompletionCallbackWithOutput< 400 typename internal::TypeUnwrapper<Output>::StorageType> 401 NewExtCallbackWithOutput(void (T::*method)(int32_t, Output, A), 402 const A& a) { 403 typedef typename internal::TypeUnwrapper<Output>::StorageType 404 OutputStorageType; 405 typedef ext::ExtCompletionCallbackWithOutput<OutputStorageType> 406 CallbackType; 407 typedef DispatcherWithOutput1< 408 typename CallbackType::TraitsType, 409 OutputStorageType, 410 void (T::*)(int32_t, Output, A), 411 typename internal::TypeUnwrapper<A>::StorageType> DispatcherType; 412 return NewCallbackWithOutputHelper<CallbackType>( 413 new DispatcherType(method, a)); 414 } 415 416 /// NewCallback() allocates a new, single-use 417 /// <code>CompletionCallback</code>. 418 /// The <code>CompletionCallback</code> must be run in order for the memory 419 /// allocated by the methods to be freed. 420 /// 421 /// @param method The method taking the callback. Method should be of type: 422 /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code> 423 /// 424 /// @param[in] a Passed to <code>method</code> when the completion callback 425 /// runs. 426 /// 427 /// @param[in] b Passed to <code>method</code> when the completion callback 428 /// runs. 429 /// 430 /// @return A <code>CompletionCallback</code>. 431 template <typename Method, typename A, typename B> 432 CompletionCallback NewCallback(Method method, const A& a, const B& b) { 433 return NewCallbackHelper(new Dispatcher2<Method, A, B>(method, a, b)); 434 } 435 436 /// NewOptionalCallback() allocates a new, single-use 437 /// <code>CompletionCallback</code> that might not run if the method 438 /// taking it can complete synchronously. Thus, if after passing the 439 /// CompletionCallback to a Pepper method, the method does not return 440 /// PP_OK_COMPLETIONPENDING, then you should manually call the 441 /// CompletionCallback's Run method, or memory will be leaked. 442 /// 443 /// @param[in] method The method taking the callback. Method should be of 444 /// type: 445 /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code> 446 /// 447 /// @param[in] a Passed to <code>method</code> when the completion callback 448 /// runs. 449 /// 450 /// @param[in] b Passed to <code>method</code> when the completion callback 451 /// runs. 452 /// 453 /// @return A <code>CompletionCallback</code>. 454 template <typename Method, typename A, typename B> 455 CompletionCallback NewOptionalCallback(Method method, const A& a, 456 const B& b) { 457 CompletionCallback cc = NewCallback(method, a, b); 458 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); 459 return cc; 460 } 461 462 /// NewCallbackWithOutput() allocates a new, single-use 463 /// <code>CompletionCallback</code> where the browser will pass an additional 464 /// parameter containing the result of the request. The 465 /// <code>CompletionCallback</code> must be run in order for the memory 466 /// allocated by the methods to be freed. 467 /// 468 /// @param[in] method The method to be invoked upon completion of the 469 /// operation. 470 /// 471 /// @param[in] a Passed to <code>method</code> when the completion callback 472 /// runs. 473 /// 474 /// @param[in] b Passed to <code>method</code> when the completion callback 475 /// runs. 476 /// 477 /// @return A <code>CompletionCallback</code>. 478 template <typename Output, typename A, typename B> 479 CompletionCallbackWithOutput< 480 typename internal::TypeUnwrapper<Output>::StorageType> 481 NewCallbackWithOutput(void (T::*method)(int32_t, Output, A, B), 482 const A& a, 483 const B& b) { 484 typedef typename internal::TypeUnwrapper<Output>::StorageType 485 OutputStorageType; 486 typedef CompletionCallbackWithOutput<OutputStorageType> CallbackType; 487 typedef DispatcherWithOutput2< 488 typename CallbackType::TraitsType, 489 OutputStorageType, 490 void (T::*)(int32_t, Output, A, B), 491 typename internal::TypeUnwrapper<A>::StorageType, 492 typename internal::TypeUnwrapper<B>::StorageType> DispatcherType; 493 return NewCallbackWithOutputHelper<CallbackType>( 494 new DispatcherType(method, a, b)); 495 } 496 497 /// Similar to NewCallbackWithOutput(), but returns an 498 /// <code>ext::ExtCompletionCallbackWithOutput</code>. 499 template <typename Output, typename A, typename B> 500 ext::ExtCompletionCallbackWithOutput< 501 typename internal::TypeUnwrapper<Output>::StorageType> 502 NewExtCallbackWithOutput(void (T::*method)(int32_t, Output, A, B), 503 const A& a, 504 const B& b) { 505 typedef typename internal::TypeUnwrapper<Output>::StorageType 506 OutputStorageType; 507 typedef ext::ExtCompletionCallbackWithOutput<OutputStorageType> 508 CallbackType; 509 typedef DispatcherWithOutput2< 510 typename CallbackType::TraitsType, 511 OutputStorageType, 512 void (T::*)(int32_t, Output, A, B), 513 typename internal::TypeUnwrapper<A>::StorageType, 514 typename internal::TypeUnwrapper<B>::StorageType> DispatcherType; 515 return NewCallbackWithOutputHelper<CallbackType>( 516 new DispatcherType(method, a, b)); 517 } 518 519 /// NewCallback() allocates a new, single-use 520 /// <code>CompletionCallback</code>. 521 /// The <code>CompletionCallback</code> must be run in order for the memory 522 /// allocated by the methods to be freed. 523 /// 524 /// @param method The method taking the callback. Method should be of type: 525 /// <code> 526 /// void (T::*)(int32_t result, const A& a, const B& b, const C& c) 527 /// </code> 528 /// 529 /// @param[in] a Passed to <code>method</code> when the completion callback 530 /// runs. 531 /// 532 /// @param[in] b Passed to <code>method</code> when the completion callback 533 /// runs. 534 /// 535 /// @param[in] c Passed to <code>method</code> when the completion callback 536 /// runs. 537 /// 538 /// @return A <code>CompletionCallback</code>. 539 template <typename Method, typename A, typename B, typename C> 540 CompletionCallback NewCallback(Method method, const A& a, const B& b, 541 const C& c) { 542 return NewCallbackHelper(new Dispatcher3<Method, A, B, C>(method, a, b, c)); 543 } 544 545 /// NewOptionalCallback() allocates a new, single-use 546 /// <code>CompletionCallback</code> that might not run if the method 547 /// taking it can complete synchronously. Thus, if after passing the 548 /// CompletionCallback to a Pepper method, the method does not return 549 /// PP_OK_COMPLETIONPENDING, then you should manually call the 550 /// CompletionCallback's Run method, or memory will be leaked. 551 /// 552 /// @param[in] method The method taking the callback. Method should be of 553 /// type: 554 /// <code> 555 /// void (T::*)(int32_t result, const A& a, const B& b, const C& c) 556 /// </code> 557 /// 558 /// @param[in] a Passed to <code>method</code> when the completion callback 559 /// runs. 560 /// 561 /// @param[in] b Passed to <code>method</code> when the completion callback 562 /// runs. 563 /// 564 /// @param[in] c Passed to <code>method</code> when the completion callback 565 /// runs. 566 /// 567 /// @return A <code>CompletionCallback</code>. 568 template <typename Method, typename A, typename B, typename C> 569 CompletionCallback NewOptionalCallback(Method method, const A& a, 570 const B& b, const C& c) { 571 CompletionCallback cc = NewCallback(method, a, b, c); 572 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); 573 return cc; 574 } 575 576 /// NewCallbackWithOutput() allocates a new, single-use 577 /// <code>CompletionCallback</code> where the browser will pass an additional 578 /// parameter containing the result of the request. The 579 /// <code>CompletionCallback</code> must be run in order for the memory 580 /// allocated by the methods to be freed. 581 /// 582 /// @param method The method to be run. 583 /// 584 /// @param[in] a Passed to <code>method</code> when the completion callback 585 /// runs. 586 /// 587 /// @param[in] b Passed to <code>method</code> when the completion callback 588 /// runs. 589 /// 590 /// @param[in] c Passed to <code>method</code> when the completion callback 591 /// runs. 592 /// 593 /// @return A <code>CompletionCallback</code>. 594 template <typename Output, typename A, typename B, typename C> 595 CompletionCallbackWithOutput< 596 typename internal::TypeUnwrapper<Output>::StorageType> 597 NewCallbackWithOutput(void (T::*method)(int32_t, Output, A, B, C), 598 const A& a, 599 const B& b, 600 const C& c) { 601 typedef typename internal::TypeUnwrapper<Output>::StorageType 602 OutputStorageType; 603 typedef CompletionCallbackWithOutput<OutputStorageType> CallbackType; 604 typedef DispatcherWithOutput3< 605 typename CallbackType::TraitsType, 606 OutputStorageType, 607 void (T::*)(int32_t, Output, A, B, C), 608 typename internal::TypeUnwrapper<A>::StorageType, 609 typename internal::TypeUnwrapper<B>::StorageType, 610 typename internal::TypeUnwrapper<C>::StorageType> DispatcherType; 611 return NewCallbackWithOutputHelper<CallbackType>( 612 new DispatcherType(method, a, b, c)); 613 } 614 615 /// Similar to NewCallbackWithOutput(), but returns an 616 /// <code>ext::ExtCompletionCallbackWithOutput</code>. 617 template <typename Output, typename A, typename B, typename C> 618 ext::ExtCompletionCallbackWithOutput< 619 typename internal::TypeUnwrapper<Output>::StorageType> 620 NewExtCallbackWithOutput(void (T::*method)(int32_t, Output, A, B, C), 621 const A& a, 622 const B& b, 623 const C& c) { 624 typedef typename internal::TypeUnwrapper<Output>::StorageType 625 OutputStorageType; 626 typedef ext::ExtCompletionCallbackWithOutput<OutputStorageType> 627 CallbackType; 628 typedef DispatcherWithOutput3< 629 typename CallbackType::TraitsType, 630 OutputStorageType, 631 void (T::*)(int32_t, Output, A, B, C), 632 typename internal::TypeUnwrapper<A>::StorageType, 633 typename internal::TypeUnwrapper<B>::StorageType, 634 typename internal::TypeUnwrapper<C>::StorageType> DispatcherType; 635 return NewCallbackWithOutputHelper<CallbackType>( 636 new DispatcherType(method, a, b, c)); 637 } 638 639 private: 640 class BackPointer { 641 public: 642 typedef CompletionCallbackFactory<T, ThreadTraits> FactoryType; 643 644 explicit BackPointer(FactoryType* factory) 645 : factory_(factory) { 646 } 647 648 void AddRef() { 649 ref_.AddRef(); 650 } 651 652 void Release() { 653 if (ref_.Release() == 0) 654 delete this; 655 } 656 657 void DropFactory() { 658 factory_ = NULL; 659 } 660 661 T* GetObject() { 662 return factory_ ? factory_->GetObject() : NULL; 663 } 664 665 private: 666 typename ThreadTraits::RefCount ref_; 667 FactoryType* factory_; 668 }; 669 670 template <typename Dispatcher> 671 class CallbackData { 672 public: 673 // Takes ownership of the given dispatcher pointer. 674 CallbackData(BackPointer* back_pointer, Dispatcher* dispatcher) 675 : back_pointer_(back_pointer), 676 dispatcher_(dispatcher) { 677 back_pointer_->AddRef(); 678 } 679 680 ~CallbackData() { 681 back_pointer_->Release(); 682 delete dispatcher_; 683 } 684 685 Dispatcher* dispatcher() { return dispatcher_; } 686 687 static void Thunk(void* user_data, int32_t result) { 688 Self* self = static_cast<Self*>(user_data); 689 T* object = self->back_pointer_->GetObject(); 690 691 // Please note that |object| may be NULL at this point. But we still need 692 // to call into Dispatcher::operator() in that case, so that it can do 693 // necessary cleanup. 694 (*self->dispatcher_)(object, result); 695 696 delete self; 697 } 698 699 private: 700 typedef CallbackData<Dispatcher> Self; 701 BackPointer* back_pointer_; // We own a ref to this refcounted object. 702 Dispatcher* dispatcher_; // We own this pointer. 703 704 // Disallow copying & assignment. 705 CallbackData(const CallbackData<Dispatcher>&); 706 CallbackData<Dispatcher>& operator=(const CallbackData<Dispatcher>&); 707 }; 708 709 template <typename Method> 710 class Dispatcher0 { 711 public: 712 Dispatcher0() : method_(NULL) {} 713 explicit Dispatcher0(Method method) : method_(method) { 714 } 715 void operator()(T* object, int32_t result) { 716 if (object) 717 (object->*method_)(result); 718 } 719 private: 720 Method method_; 721 }; 722 723 template <typename Traits, typename Output, typename Method> 724 class DispatcherWithOutput0 { 725 public: 726 typedef Output OutputType; 727 728 DispatcherWithOutput0() 729 : method_(NULL), 730 output_() { 731 Traits::Initialize(&output_); 732 } 733 DispatcherWithOutput0(Method method) 734 : method_(method), 735 output_() { 736 Traits::Initialize(&output_); 737 } 738 void operator()(T* object, int32_t result) { 739 // We must call Traits::StorageToPluginArg() even if we don't need to call 740 // the callback anymore, otherwise we may leak resource or var references. 741 if (object) 742 (object->*method_)(result, Traits::StorageToPluginArg(output_)); 743 else 744 Traits::StorageToPluginArg(output_); 745 } 746 typename Traits::StorageType* output() { 747 return &output_; 748 } 749 private: 750 Method method_; 751 752 typename Traits::StorageType output_; 753 }; 754 755 template <typename Method, typename A> 756 class Dispatcher1 { 757 public: 758 Dispatcher1() 759 : method_(NULL), 760 a_() { 761 } 762 Dispatcher1(Method method, const A& a) 763 : method_(method), 764 a_(a) { 765 } 766 void operator()(T* object, int32_t result) { 767 if (object) 768 (object->*method_)(result, a_); 769 } 770 private: 771 Method method_; 772 A a_; 773 }; 774 775 template <typename Traits, typename Output, typename Method, typename A> 776 class DispatcherWithOutput1 { 777 public: 778 typedef Output OutputType; 779 780 DispatcherWithOutput1() 781 : method_(NULL), 782 a_(), 783 output_() { 784 Traits::Initialize(&output_); 785 } 786 DispatcherWithOutput1(Method method, const A& a) 787 : method_(method), 788 a_(a), 789 output_() { 790 Traits::Initialize(&output_); 791 } 792 void operator()(T* object, int32_t result) { 793 // We must call Traits::StorageToPluginArg() even if we don't need to call 794 // the callback anymore, otherwise we may leak resource or var references. 795 if (object) 796 (object->*method_)(result, Traits::StorageToPluginArg(output_), a_); 797 else 798 Traits::StorageToPluginArg(output_); 799 } 800 typename Traits::StorageType* output() { 801 return &output_; 802 } 803 private: 804 Method method_; 805 A a_; 806 807 typename Traits::StorageType output_; 808 }; 809 810 template <typename Method, typename A, typename B> 811 class Dispatcher2 { 812 public: 813 Dispatcher2() 814 : method_(NULL), 815 a_(), 816 b_() { 817 } 818 Dispatcher2(Method method, const A& a, const B& b) 819 : method_(method), 820 a_(a), 821 b_(b) { 822 } 823 void operator()(T* object, int32_t result) { 824 if (object) 825 (object->*method_)(result, a_, b_); 826 } 827 private: 828 Method method_; 829 A a_; 830 B b_; 831 }; 832 833 template <typename Traits, 834 typename Output, 835 typename Method, 836 typename A, 837 typename B> 838 class DispatcherWithOutput2 { 839 public: 840 typedef Output OutputType; 841 842 DispatcherWithOutput2() 843 : method_(NULL), 844 a_(), 845 b_(), 846 output_() { 847 Traits::Initialize(&output_); 848 } 849 DispatcherWithOutput2(Method method, const A& a, const B& b) 850 : method_(method), 851 a_(a), 852 b_(b), 853 output_() { 854 Traits::Initialize(&output_); 855 } 856 void operator()(T* object, int32_t result) { 857 // We must call Traits::StorageToPluginArg() even if we don't need to call 858 // the callback anymore, otherwise we may leak resource or var references. 859 if (object) 860 (object->*method_)(result, Traits::StorageToPluginArg(output_), a_, b_); 861 else 862 Traits::StorageToPluginArg(output_); 863 } 864 typename Traits::StorageType* output() { 865 return &output_; 866 } 867 private: 868 Method method_; 869 A a_; 870 B b_; 871 872 typename Traits::StorageType output_; 873 }; 874 875 template <typename Method, typename A, typename B, typename C> 876 class Dispatcher3 { 877 public: 878 Dispatcher3() 879 : method_(NULL), 880 a_(), 881 b_(), 882 c_() { 883 } 884 Dispatcher3(Method method, const A& a, const B& b, const C& c) 885 : method_(method), 886 a_(a), 887 b_(b), 888 c_(c) { 889 } 890 void operator()(T* object, int32_t result) { 891 if (object) 892 (object->*method_)(result, a_, b_, c_); 893 } 894 private: 895 Method method_; 896 A a_; 897 B b_; 898 C c_; 899 }; 900 901 template <typename Traits, 902 typename Output, 903 typename Method, 904 typename A, 905 typename B, 906 typename C> 907 class DispatcherWithOutput3 { 908 public: 909 typedef Output OutputType; 910 911 DispatcherWithOutput3() 912 : method_(NULL), 913 a_(), 914 b_(), 915 c_(), 916 output_() { 917 Traits::Initialize(&output_); 918 } 919 DispatcherWithOutput3(Method method, const A& a, const B& b, const C& c) 920 : method_(method), 921 a_(a), 922 b_(b), 923 c_(c), 924 output_() { 925 Traits::Initialize(&output_); 926 } 927 void operator()(T* object, int32_t result) { 928 // We must call Traits::StorageToPluginArg() even if we don't need to call 929 // the callback anymore, otherwise we may leak resource or var references. 930 if (object) { 931 (object->*method_)(result, Traits::StorageToPluginArg(output_), 932 a_, b_, c_); 933 } else { 934 Traits::StorageToPluginArg(output_); 935 } 936 } 937 typename Traits::StorageType* output() { 938 return &output_; 939 } 940 private: 941 Method method_; 942 A a_; 943 B b_; 944 C c_; 945 946 typename Traits::StorageType output_; 947 }; 948 949 // Creates the back pointer object and takes a reference to it. This assumes 950 // either that the lock is held or that it is not needed. 951 void InitBackPointer() { 952 back_pointer_ = new BackPointer(this); 953 back_pointer_->AddRef(); 954 } 955 956 // Releases our reference to the back pointer object and clears the pointer. 957 // This assumes either that the lock is held or that it is not needed. 958 void ResetBackPointer() { 959 back_pointer_->DropFactory(); 960 back_pointer_->Release(); 961 back_pointer_ = NULL; 962 } 963 964 // Takes ownership of the dispatcher pointer, which should be heap allocated. 965 template <typename Dispatcher> 966 CompletionCallback NewCallbackHelper(Dispatcher* dispatcher) { 967 typename ThreadTraits::AutoLock lock(lock_); 968 969 PP_DCHECK(object_); // Expects a non-null object! 970 return CompletionCallback( 971 &CallbackData<Dispatcher>::Thunk, 972 new CallbackData<Dispatcher>(back_pointer_, dispatcher)); 973 } 974 975 // Takes ownership of the dispatcher pointer, which should be heap allocated. 976 template <typename Callback, typename Dispatcher> 977 Callback NewCallbackWithOutputHelper(Dispatcher* dispatcher) { 978 typename ThreadTraits::AutoLock lock(lock_); 979 980 PP_DCHECK(object_); // Expects a non-null object! 981 CallbackData<Dispatcher>* data = 982 new CallbackData<Dispatcher>(back_pointer_, dispatcher); 983 984 return Callback(&CallbackData<Dispatcher>::Thunk, 985 data, 986 data->dispatcher()->output()); 987 } 988 989 // Disallowed: 990 CompletionCallbackFactory(const CompletionCallbackFactory&); 991 CompletionCallbackFactory& operator=(const CompletionCallbackFactory&); 992 993 // Never changed once initialized so does not need protection by the lock. 994 T* object_; 995 996 // Protects the back pointer. 997 typename ThreadTraits::Lock lock_; 998 999 // Protected by the lock. This will get reset when you do CancelAll, for 1000 // example. 1001 BackPointer* back_pointer_; 1002 }; 1003 1004 } // namespace pp 1005 1006 #endif // PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_ 1007