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 template <typename T, typename ThreadTraits = ThreadSafeThreadTraits> 189 class CompletionCallbackFactory { 190 public: 191 192 /// This constructor creates a <code>CompletionCallbackFactory</code> 193 /// bound to an object. If the constructor is called without an argument, 194 /// the default value of <code>NULL</code> is used. The user then must call 195 /// Initialize() to initialize the object. 196 /// 197 /// param[in] object Optional parameter. An object whose member functions 198 /// are to be bound to CompletionCallbacks created by this 199 /// <code>CompletionCallbackFactory</code>. The default value of this 200 /// parameter is <code>NULL</code>. 201 explicit CompletionCallbackFactory(T* object = NULL) 202 : object_(object) { 203 // Assume that we don't need to lock since construction should be complete 204 // before the pointer is used on another thread. 205 InitBackPointer(); 206 } 207 208 /// Destructor. 209 ~CompletionCallbackFactory() { 210 // Assume that we don't need to lock since this object should not be used 211 // from multiple threads during destruction. 212 ResetBackPointer(); 213 } 214 215 /// CancelAll() cancels all <code>CompletionCallbacks</code> allocated from 216 /// this factory. 217 void CancelAll() { 218 typename ThreadTraits::AutoLock lock(lock_); 219 220 ResetBackPointer(); 221 InitBackPointer(); 222 } 223 224 /// Initialize() binds the <code>CallbackFactory</code> to a particular 225 /// object. Use this when the object is not available at 226 /// <code>CallbackFactory</code> creation, and the <code>NULL</code> default 227 /// is passed to the constructor. The object may only be initialized once, 228 /// either by the constructor, or by a call to Initialize(). 229 /// 230 /// This class may not be used on any thread until initialization is complete. 231 /// 232 /// @param[in] object The object whose member functions are to be bound to 233 /// the <code>CompletionCallback</code> created by this 234 /// <code>CompletionCallbackFactory</code>. 235 void Initialize(T* object) { 236 PP_DCHECK(object); 237 PP_DCHECK(!object_); // May only initialize once! 238 object_ = object; 239 } 240 241 /// GetObject() returns the object that was passed at initialization to 242 /// Intialize(). 243 /// 244 /// @return the object passed to the constructor or Intialize(). 245 T* GetObject() { 246 return object_; 247 } 248 249 /// NewCallback allocates a new, single-use <code>CompletionCallback</code>. 250 /// The <code>CompletionCallback</code> must be run in order for the memory 251 /// allocated by the methods to be freed. 252 /// 253 /// @param[in] method The method to be invoked upon completion of the 254 /// operation. 255 /// 256 /// @return A <code>CompletionCallback</code>. 257 template <typename Method> 258 CompletionCallback NewCallback(Method method) { 259 return NewCallbackHelper(new Dispatcher0<Method>(method)); 260 } 261 262 /// NewOptionalCallback() allocates a new, single-use 263 /// <code>CompletionCallback</code> that might not run if the method 264 /// taking it can complete synchronously. Thus, if after passing the 265 /// CompletionCallback to a Pepper method, the method does not return 266 /// PP_OK_COMPLETIONPENDING, then you should manually call the 267 /// CompletionCallback's Run method, or memory will be leaked. 268 /// 269 /// @param[in] method The method to be invoked upon completion of the 270 /// operation. 271 /// 272 /// @return A <code>CompletionCallback</code>. 273 template <typename Method> 274 CompletionCallback NewOptionalCallback(Method method) { 275 CompletionCallback cc = NewCallback(method); 276 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); 277 return cc; 278 } 279 280 /// NewCallbackWithOutput() allocates a new, single-use 281 /// <code>CompletionCallback</code> where the browser will pass an additional 282 /// parameter containing the result of the request. The 283 /// <code>CompletionCallback</code> must be run in order for the memory 284 /// allocated by the methods to be freed. 285 /// 286 /// @param[in] method The method to be invoked upon completion of the 287 /// operation. 288 /// 289 /// @return A <code>CompletionCallback</code>. 290 template <typename Output> 291 CompletionCallbackWithOutput< 292 typename internal::TypeUnwrapper<Output>::StorageType> 293 NewCallbackWithOutput(void (T::*method)(int32_t, Output)) { 294 return NewCallbackWithOutputHelper(new DispatcherWithOutput0< 295 typename internal::TypeUnwrapper<Output>::StorageType, 296 void (T::*)(int32_t, Output)>(method)); 297 } 298 299 /// NewCallback() allocates a new, single-use <code>CompletionCallback</code>. 300 /// The <code>CompletionCallback</code> must be run in order for the memory 301 /// allocated by the methods to be freed. 302 /// 303 /// @param[in] method The method to be invoked upon completion of the 304 /// operation. Method should be of type: 305 /// <code>void (T::*)(int32_t result, const A& a)</code> 306 /// 307 /// @param[in] a Passed to <code>method</code> when the completion callback 308 /// runs. 309 /// 310 /// @return A <code>CompletionCallback</code>. 311 template <typename Method, typename A> 312 CompletionCallback NewCallback(Method method, const A& a) { 313 return NewCallbackHelper(new Dispatcher1<Method, A>(method, a)); 314 } 315 316 /// NewOptionalCallback() allocates a new, single-use 317 /// <code>CompletionCallback</code> that might not run if the method 318 /// taking it can complete synchronously. Thus, if after passing the 319 /// CompletionCallback to a Pepper method, the method does not return 320 /// PP_OK_COMPLETIONPENDING, then you should manually call the 321 /// CompletionCallback's Run method, or memory will be leaked. 322 /// 323 /// @param[in] method The method to be invoked upon completion of the 324 /// operation. Method should be of type: 325 /// <code>void (T::*)(int32_t result, const A& a)</code> 326 /// 327 /// @param[in] a Passed to <code>method</code> when the completion callback 328 /// runs. 329 /// 330 /// @return A <code>CompletionCallback</code>. 331 template <typename Method, typename A> 332 CompletionCallback NewOptionalCallback(Method method, const A& a) { 333 CompletionCallback cc = NewCallback(method, a); 334 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); 335 return cc; 336 } 337 338 /// NewCallbackWithOutput() allocates a new, single-use 339 /// <code>CompletionCallback</code> where the browser will pass an additional 340 /// parameter containing the result of the request. The 341 /// <code>CompletionCallback</code> must be run in order for the memory 342 /// allocated by the methods to be freed. 343 /// 344 /// @param[in] method The method to be invoked upon completion of the 345 /// operation. 346 /// 347 /// @param[in] a Passed to <code>method</code> when the completion callback 348 /// runs. 349 /// 350 /// @return A <code>CompletionCallback</code>. 351 template <typename Output, typename A> 352 CompletionCallbackWithOutput< 353 typename internal::TypeUnwrapper<Output>::StorageType> 354 NewCallbackWithOutput(void (T::*method)(int32_t, Output, A), 355 const A& a) { 356 return NewCallbackWithOutputHelper(new DispatcherWithOutput1< 357 typename internal::TypeUnwrapper<Output>::StorageType, 358 void (T::*)(int32_t, Output, A), 359 typename internal::TypeUnwrapper<A>::StorageType>(method, a)); 360 } 361 362 /// NewCallback() allocates a new, single-use 363 /// <code>CompletionCallback</code>. 364 /// The <code>CompletionCallback</code> must be run in order for the memory 365 /// allocated by the methods to be freed. 366 /// 367 /// @param method The method taking the callback. Method should be of type: 368 /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code> 369 /// 370 /// @param[in] a Passed to <code>method</code> when the completion callback 371 /// runs. 372 /// 373 /// @param[in] b Passed to <code>method</code> when the completion callback 374 /// runs. 375 /// 376 /// @return A <code>CompletionCallback</code>. 377 template <typename Method, typename A, typename B> 378 CompletionCallback NewCallback(Method method, const A& a, const B& b) { 379 return NewCallbackHelper(new Dispatcher2<Method, A, B>(method, a, b)); 380 } 381 382 /// NewOptionalCallback() allocates a new, single-use 383 /// <code>CompletionCallback</code> that might not run if the method 384 /// taking it can complete synchronously. Thus, if after passing the 385 /// CompletionCallback to a Pepper method, the method does not return 386 /// PP_OK_COMPLETIONPENDING, then you should manually call the 387 /// CompletionCallback's Run method, or memory will be leaked. 388 /// 389 /// @param[in] method The method taking the callback. Method should be of 390 /// type: 391 /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code> 392 /// 393 /// @param[in] a Passed to <code>method</code> when the completion callback 394 /// runs. 395 /// 396 /// @param[in] b Passed to <code>method</code> when the completion callback 397 /// runs. 398 /// 399 /// @return A <code>CompletionCallback</code>. 400 template <typename Method, typename A, typename B> 401 CompletionCallback NewOptionalCallback(Method method, const A& a, 402 const B& b) { 403 CompletionCallback cc = NewCallback(method, a, b); 404 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); 405 return cc; 406 } 407 408 /// NewCallbackWithOutput() allocates a new, single-use 409 /// <code>CompletionCallback</code> where the browser will pass an additional 410 /// parameter containing the result of the request. The 411 /// <code>CompletionCallback</code> must be run in order for the memory 412 /// allocated by the methods to be freed. 413 /// 414 /// @param[in] method The method to be invoked upon completion of the 415 /// operation. 416 /// 417 /// @param[in] a Passed to <code>method</code> when the completion callback 418 /// runs. 419 /// 420 /// @param[in] b Passed to <code>method</code> when the completion callback 421 /// runs. 422 /// 423 /// @return A <code>CompletionCallback</code>. 424 template <typename Output, typename A, typename B> 425 CompletionCallbackWithOutput< 426 typename internal::TypeUnwrapper<Output>::StorageType> 427 NewCallbackWithOutput(void (T::*method)(int32_t, Output, A, B), 428 const A& a, 429 const B& b) { 430 return NewCallbackWithOutputHelper(new DispatcherWithOutput2< 431 typename internal::TypeUnwrapper<Output>::StorageType, 432 void (T::*)(int32_t, Output, A, B), 433 typename internal::TypeUnwrapper<A>::StorageType, 434 typename internal::TypeUnwrapper<B>::StorageType>(method, a, b)); 435 } 436 437 /// NewCallback() allocates a new, single-use 438 /// <code>CompletionCallback</code>. 439 /// The <code>CompletionCallback</code> must be run in order for the memory 440 /// allocated by the methods to be freed. 441 /// 442 /// @param method The method taking the callback. Method should be of type: 443 /// <code> 444 /// void (T::*)(int32_t result, const A& a, const B& b, const C& c) 445 /// </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 /// @param[in] c Passed to <code>method</code> when the completion callback 454 /// runs. 455 /// 456 /// @return A <code>CompletionCallback</code>. 457 template <typename Method, typename A, typename B, typename C> 458 CompletionCallback NewCallback(Method method, const A& a, const B& b, 459 const C& c) { 460 return NewCallbackHelper(new Dispatcher3<Method, A, B, C>(method, a, b, c)); 461 } 462 463 /// NewOptionalCallback() allocates a new, single-use 464 /// <code>CompletionCallback</code> that might not run if the method 465 /// taking it can complete synchronously. Thus, if after passing the 466 /// CompletionCallback to a Pepper method, the method does not return 467 /// PP_OK_COMPLETIONPENDING, then you should manually call the 468 /// CompletionCallback's Run method, or memory will be leaked. 469 /// 470 /// @param[in] method The method taking the callback. Method should be of 471 /// type: 472 /// <code> 473 /// void (T::*)(int32_t result, const A& a, const B& b, const C& c) 474 /// </code> 475 /// 476 /// @param[in] a Passed to <code>method</code> when the completion callback 477 /// runs. 478 /// 479 /// @param[in] b Passed to <code>method</code> when the completion callback 480 /// runs. 481 /// 482 /// @param[in] c Passed to <code>method</code> when the completion callback 483 /// runs. 484 /// 485 /// @return A <code>CompletionCallback</code>. 486 template <typename Method, typename A, typename B, typename C> 487 CompletionCallback NewOptionalCallback(Method method, const A& a, 488 const B& b, const C& c) { 489 CompletionCallback cc = NewCallback(method, a, b, c); 490 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); 491 return cc; 492 } 493 494 /// NewCallbackWithOutput() allocates a new, single-use 495 /// <code>CompletionCallback</code> where the browser will pass an additional 496 /// parameter containing the result of the request. The 497 /// <code>CompletionCallback</code> must be run in order for the memory 498 /// allocated by the methods to be freed. 499 /// 500 /// @param method The method to be run. 501 /// 502 /// @param[in] a Passed to <code>method</code> when the completion callback 503 /// runs. 504 /// 505 /// @param[in] b Passed to <code>method</code> when the completion callback 506 /// runs. 507 /// 508 /// @param[in] c Passed to <code>method</code> when the completion callback 509 /// runs. 510 /// 511 /// @return A <code>CompletionCallback</code>. 512 template <typename Output, typename A, typename B, typename C> 513 CompletionCallbackWithOutput< 514 typename internal::TypeUnwrapper<Output>::StorageType> 515 NewCallbackWithOutput(void (T::*method)(int32_t, Output, A, B, C), 516 const A& a, 517 const B& b, 518 const C& c) { 519 return NewCallbackWithOutputHelper(new DispatcherWithOutput3< 520 typename internal::TypeUnwrapper<Output>::StorageType, 521 void (T::*)(int32_t, Output, A, B, C), 522 typename internal::TypeUnwrapper<A>::StorageType, 523 typename internal::TypeUnwrapper<B>::StorageType, 524 typename internal::TypeUnwrapper<C>::StorageType>(method, a, b, c)); 525 } 526 527 private: 528 class BackPointer { 529 public: 530 typedef CompletionCallbackFactory<T, ThreadTraits> FactoryType; 531 532 explicit BackPointer(FactoryType* factory) 533 : factory_(factory) { 534 } 535 536 void AddRef() { 537 ref_.AddRef(); 538 } 539 540 void Release() { 541 if (ref_.Release() == 0) 542 delete this; 543 } 544 545 void DropFactory() { 546 factory_ = NULL; 547 } 548 549 T* GetObject() { 550 return factory_ ? factory_->GetObject() : NULL; 551 } 552 553 private: 554 typename ThreadTraits::RefCount ref_; 555 FactoryType* factory_; 556 }; 557 558 template <typename Dispatcher> 559 class CallbackData { 560 public: 561 // Takes ownership of the given dispatcher pointer. 562 CallbackData(BackPointer* back_pointer, Dispatcher* dispatcher) 563 : back_pointer_(back_pointer), 564 dispatcher_(dispatcher) { 565 back_pointer_->AddRef(); 566 } 567 568 ~CallbackData() { 569 back_pointer_->Release(); 570 delete dispatcher_; 571 } 572 573 Dispatcher* dispatcher() { return dispatcher_; } 574 575 static void Thunk(void* user_data, int32_t result) { 576 Self* self = static_cast<Self*>(user_data); 577 T* object = self->back_pointer_->GetObject(); 578 579 // Please note that |object| may be NULL at this point. But we still need 580 // to call into Dispatcher::operator() in that case, so that it can do 581 // necessary cleanup. 582 (*self->dispatcher_)(object, result); 583 584 delete self; 585 } 586 587 private: 588 typedef CallbackData<Dispatcher> Self; 589 BackPointer* back_pointer_; // We own a ref to this refcounted object. 590 Dispatcher* dispatcher_; // We own this pointer. 591 592 // Disallow copying & assignment. 593 CallbackData(const CallbackData<Dispatcher>&); 594 CallbackData<Dispatcher>& operator=(const CallbackData<Dispatcher>&); 595 }; 596 597 template <typename Method> 598 class Dispatcher0 { 599 public: 600 Dispatcher0() : method_(NULL) {} 601 explicit Dispatcher0(Method method) : method_(method) { 602 } 603 void operator()(T* object, int32_t result) { 604 if (object) 605 (object->*method_)(result); 606 } 607 private: 608 Method method_; 609 }; 610 611 template <typename Output, typename Method> 612 class DispatcherWithOutput0 { 613 public: 614 typedef Output OutputType; 615 typedef internal::CallbackOutputTraits<Output> Traits; 616 617 DispatcherWithOutput0() 618 : method_(NULL), 619 output_() { 620 Traits::Initialize(&output_); 621 } 622 DispatcherWithOutput0(Method method) 623 : method_(method), 624 output_() { 625 Traits::Initialize(&output_); 626 } 627 void operator()(T* object, int32_t result) { 628 // We must call Traits::StorageToPluginArg() even if we don't need to call 629 // the callback anymore, otherwise we may leak resource or var references. 630 if (object) 631 (object->*method_)(result, Traits::StorageToPluginArg(output_)); 632 else 633 Traits::StorageToPluginArg(output_); 634 } 635 typename Traits::StorageType* output() { 636 return &output_; 637 } 638 private: 639 Method method_; 640 641 typename Traits::StorageType output_; 642 }; 643 644 template <typename Method, typename A> 645 class Dispatcher1 { 646 public: 647 Dispatcher1() 648 : method_(NULL), 649 a_() { 650 } 651 Dispatcher1(Method method, const A& a) 652 : method_(method), 653 a_(a) { 654 } 655 void operator()(T* object, int32_t result) { 656 if (object) 657 (object->*method_)(result, a_); 658 } 659 private: 660 Method method_; 661 A a_; 662 }; 663 664 template <typename Output, typename Method, typename A> 665 class DispatcherWithOutput1 { 666 public: 667 typedef Output OutputType; 668 typedef internal::CallbackOutputTraits<Output> Traits; 669 670 DispatcherWithOutput1() 671 : method_(NULL), 672 a_(), 673 output_() { 674 Traits::Initialize(&output_); 675 } 676 DispatcherWithOutput1(Method method, const A& a) 677 : method_(method), 678 a_(a), 679 output_() { 680 Traits::Initialize(&output_); 681 } 682 void operator()(T* object, int32_t result) { 683 // We must call Traits::StorageToPluginArg() even if we don't need to call 684 // the callback anymore, otherwise we may leak resource or var references. 685 if (object) 686 (object->*method_)(result, Traits::StorageToPluginArg(output_), a_); 687 else 688 Traits::StorageToPluginArg(output_); 689 } 690 typename Traits::StorageType* output() { 691 return &output_; 692 } 693 private: 694 Method method_; 695 A a_; 696 697 typename Traits::StorageType output_; 698 }; 699 700 template <typename Method, typename A, typename B> 701 class Dispatcher2 { 702 public: 703 Dispatcher2() 704 : method_(NULL), 705 a_(), 706 b_() { 707 } 708 Dispatcher2(Method method, const A& a, const B& b) 709 : method_(method), 710 a_(a), 711 b_(b) { 712 } 713 void operator()(T* object, int32_t result) { 714 if (object) 715 (object->*method_)(result, a_, b_); 716 } 717 private: 718 Method method_; 719 A a_; 720 B b_; 721 }; 722 723 template <typename Output, typename Method, typename A, typename B> 724 class DispatcherWithOutput2 { 725 public: 726 typedef Output OutputType; 727 typedef internal::CallbackOutputTraits<Output> Traits; 728 729 DispatcherWithOutput2() 730 : method_(NULL), 731 a_(), 732 b_(), 733 output_() { 734 Traits::Initialize(&output_); 735 } 736 DispatcherWithOutput2(Method method, const A& a, const B& b) 737 : method_(method), 738 a_(a), 739 b_(b), 740 output_() { 741 Traits::Initialize(&output_); 742 } 743 void operator()(T* object, int32_t result) { 744 // We must call Traits::StorageToPluginArg() even if we don't need to call 745 // the callback anymore, otherwise we may leak resource or var references. 746 if (object) 747 (object->*method_)(result, Traits::StorageToPluginArg(output_), a_, b_); 748 else 749 Traits::StorageToPluginArg(output_); 750 } 751 typename Traits::StorageType* output() { 752 return &output_; 753 } 754 private: 755 Method method_; 756 A a_; 757 B b_; 758 759 typename Traits::StorageType output_; 760 }; 761 762 template <typename Method, typename A, typename B, typename C> 763 class Dispatcher3 { 764 public: 765 Dispatcher3() 766 : method_(NULL), 767 a_(), 768 b_(), 769 c_() { 770 } 771 Dispatcher3(Method method, const A& a, const B& b, const C& c) 772 : method_(method), 773 a_(a), 774 b_(b), 775 c_(c) { 776 } 777 void operator()(T* object, int32_t result) { 778 if (object) 779 (object->*method_)(result, a_, b_, c_); 780 } 781 private: 782 Method method_; 783 A a_; 784 B b_; 785 C c_; 786 }; 787 788 template <typename Output, typename Method, typename A, typename B, 789 typename C> 790 class DispatcherWithOutput3 { 791 public: 792 typedef Output OutputType; 793 typedef internal::CallbackOutputTraits<Output> Traits; 794 795 DispatcherWithOutput3() 796 : method_(NULL), 797 a_(), 798 b_(), 799 c_(), 800 output_() { 801 Traits::Initialize(&output_); 802 } 803 DispatcherWithOutput3(Method method, const A& a, const B& b, const C& c) 804 : method_(method), 805 a_(a), 806 b_(b), 807 c_(c), 808 output_() { 809 Traits::Initialize(&output_); 810 } 811 void operator()(T* object, int32_t result) { 812 // We must call Traits::StorageToPluginArg() even if we don't need to call 813 // the callback anymore, otherwise we may leak resource or var references. 814 if (object) { 815 (object->*method_)(result, Traits::StorageToPluginArg(output_), 816 a_, b_, c_); 817 } else { 818 Traits::StorageToPluginArg(output_); 819 } 820 } 821 typename Traits::StorageType* output() { 822 return &output_; 823 } 824 private: 825 Method method_; 826 A a_; 827 B b_; 828 C c_; 829 830 typename Traits::StorageType output_; 831 }; 832 833 // Creates the back pointer object and takes a reference to it. This assumes 834 // either that the lock is held or that it is not needed. 835 void InitBackPointer() { 836 back_pointer_ = new BackPointer(this); 837 back_pointer_->AddRef(); 838 } 839 840 // Releases our reference to the back pointer object and clears the pointer. 841 // This assumes either that the lock is held or that it is not needed. 842 void ResetBackPointer() { 843 back_pointer_->DropFactory(); 844 back_pointer_->Release(); 845 back_pointer_ = NULL; 846 } 847 848 // Takes ownership of the dispatcher pointer, which should be heap allocated. 849 template <typename Dispatcher> 850 CompletionCallback NewCallbackHelper(Dispatcher* dispatcher) { 851 typename ThreadTraits::AutoLock lock(lock_); 852 853 PP_DCHECK(object_); // Expects a non-null object! 854 return CompletionCallback( 855 &CallbackData<Dispatcher>::Thunk, 856 new CallbackData<Dispatcher>(back_pointer_, dispatcher)); 857 } 858 859 // Takes ownership of the dispatcher pointer, which should be heap allocated. 860 template <typename Dispatcher> CompletionCallbackWithOutput< 861 typename internal::TypeUnwrapper< 862 typename Dispatcher::OutputType>::StorageType> 863 NewCallbackWithOutputHelper(Dispatcher* dispatcher) { 864 typename ThreadTraits::AutoLock lock(lock_); 865 866 PP_DCHECK(object_); // Expects a non-null object! 867 CallbackData<Dispatcher>* data = 868 new CallbackData<Dispatcher>(back_pointer_, dispatcher); 869 870 return CompletionCallbackWithOutput<typename Dispatcher::OutputType>( 871 &CallbackData<Dispatcher>::Thunk, 872 data, 873 data->dispatcher()->output()); 874 } 875 876 // Disallowed: 877 CompletionCallbackFactory(const CompletionCallbackFactory&); 878 CompletionCallbackFactory& operator=(const CompletionCallbackFactory&); 879 880 // Never changed once initialized so does not need protection by the lock. 881 T* object_; 882 883 // Protects the back pointer. 884 typename ThreadTraits::Lock lock_; 885 886 // Protected by the lock. This will get reset when you do CancelAll, for 887 // example. 888 BackPointer* back_pointer_; 889 }; 890 891 } // namespace pp 892 893 #endif // PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_ 894