OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef PPAPI_CPP_COMPLETION_CALLBACK_H_ | 5 #ifndef PPAPI_CPP_COMPLETION_CALLBACK_H_ |
6 #define PPAPI_CPP_COMPLETION_CALLBACK_H_ | 6 #define PPAPI_CPP_COMPLETION_CALLBACK_H_ |
7 | 7 |
8 #include "ppapi/c/pp_completion_callback.h" | 8 #include "ppapi/c/pp_completion_callback.h" |
9 #include "ppapi/c/pp_errors.h" | 9 #include "ppapi/c/pp_errors.h" |
10 #include "ppapi/cpp/logging.h" | 10 #include "ppapi/cpp/logging.h" |
11 #include "ppapi/cpp/module.h" | 11 #include "ppapi/cpp/non_thread_safe_ref_count.h" |
12 | 12 |
13 /// @file | 13 /// @file |
14 /// This file defines the API to create and run a callback. | 14 /// This file defines the API to create and run a callback. |
15 namespace pp { | 15 namespace pp { |
16 | 16 |
17 /// This API enables you to implement and receive callbacks when | 17 /// This API enables you to implement and receive callbacks when |
18 /// Pepper operations complete asynchronously. | 18 /// Pepper operations complete asynchronously. |
19 class CompletionCallback { | 19 class CompletionCallback { |
20 public: | 20 public: |
21 /// The default constructor will create a blocking | 21 /// The default constructor will create a blocking |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 }; | 149 }; |
150 | 150 |
151 /// BlockUntilComplete() is used in place of an actual completion callback | 151 /// BlockUntilComplete() is used in place of an actual completion callback |
152 /// to request blocking behavior. If specified, the calling thread will block | 152 /// to request blocking behavior. If specified, the calling thread will block |
153 /// until the function completes. Blocking completion callbacks are only | 153 /// until the function completes. Blocking completion callbacks are only |
154 /// allowed from background threads. | 154 /// allowed from background threads. |
155 /// | 155 /// |
156 /// @return A <code>CompletionCallback</code> corresponding to a NULL callback. | 156 /// @return A <code>CompletionCallback</code> corresponding to a NULL callback. |
157 CompletionCallback BlockUntilComplete(); | 157 CompletionCallback BlockUntilComplete(); |
158 | 158 |
| 159 /// CompletionCallbackFactory<T> may be used to create CompletionCallback |
| 160 /// objects that are bound to member functions. |
| 161 /// |
| 162 /// If a factory is destroyed, then any pending callbacks will be cancelled |
| 163 /// preventing any bound member functions from being called. The CancelAll() |
| 164 /// method allows pending callbacks to be cancelled without destroying the |
| 165 /// factory. |
| 166 /// |
| 167 /// <strong>Note: </strong><code>CompletionCallbackFactory<T></code> isn't |
| 168 /// thread safe, but you can make it more thread-friendly by passing a |
| 169 /// thread-safe refcounting class as the second template element. However, it |
| 170 /// only guarantees safety for creating a callback from another thread, the |
| 171 /// callback itself needs to execute on the same thread as the thread that |
| 172 /// creates/destroys the factory. With this restriction, it is safe to create |
| 173 /// the <code>CompletionCallbackFactory</code> on the main thread, create |
| 174 /// callbacks from any thread and pass them to CallOnMainThread(). |
| 175 /// |
| 176 /// <strong>Example: </strong> |
| 177 /// |
| 178 /// @code |
| 179 /// |
| 180 /// class MyHandler { |
| 181 /// public: |
| 182 /// // If an compiler warns on following using |this| in the initializer |
| 183 /// // list, use PP_ALLOW_THIS_IN_INITIALIZER_LIST macro. |
| 184 /// MyHandler() : factory_(this), offset_(0) { |
| 185 /// } |
| 186 /// |
| 187 /// void ProcessFile(const FileRef& file) { |
| 188 /// CompletionCallback cc = factory_.NewRequiredCallback( |
| 189 /// &MyHandler::DidOpen); |
| 190 /// int32_t rv = fio_.Open(file, PP_FileOpenFlag_Read, cc); |
| 191 /// CHECK(rv == PP_OK_COMPLETIONPENDING); |
| 192 /// } |
| 193 /// |
| 194 /// private: |
| 195 /// CompletionCallback NewCallback() { |
| 196 /// return factory_.NewCallback(&MyHandler::DidCompleteIO); |
| 197 /// } |
| 198 /// |
| 199 /// void DidOpen(int32_t result) { |
| 200 /// if (result == PP_OK) { |
| 201 /// // The file is open, and we can begin reading. |
| 202 /// offset_ = 0; |
| 203 /// ReadMore(); |
| 204 /// } else { |
| 205 /// // Failed to open the file with error given by 'result'. |
| 206 /// } |
| 207 /// } |
| 208 /// |
| 209 /// void DidRead(int32_t result) { |
| 210 /// if (result > 0) { |
| 211 /// // buf_ now contains 'result' number of bytes from the file. |
| 212 /// ProcessBytes(buf_, result); |
| 213 /// offset_ += result; |
| 214 /// ReadMore(); |
| 215 /// } else { |
| 216 /// // Done reading (possibly with an error given by 'result'). |
| 217 /// } |
| 218 /// } |
| 219 /// |
| 220 /// void ReadMore() { |
| 221 /// CompletionCallback cc = |
| 222 /// factory_.NewOptionalCallback(&MyHandler::DidRead); |
| 223 /// int32_t rv = fio_.Read(offset_, buf_, sizeof(buf_), |
| 224 /// cc.pp_completion_callback()); |
| 225 /// if (rv != PP_OK_COMPLETIONPENDING) |
| 226 /// cc.Run(rv); |
| 227 /// } |
| 228 /// |
| 229 /// void ProcessBytes(const char* bytes, int32_t length) { |
| 230 /// // Do work ... |
| 231 /// } |
| 232 /// |
| 233 /// pp::CompletionCallbackFactory<MyHandler> factory_; |
| 234 /// pp::FileIO fio_; |
| 235 /// char buf_[4096]; |
| 236 /// int64_t offset_; |
| 237 /// }; |
| 238 /// |
| 239 /// @endcode |
| 240 /// |
| 241 template <typename T, typename RefCount = NonThreadSafeRefCount> |
| 242 class CompletionCallbackFactory { |
| 243 public: |
| 244 |
| 245 /// This constructor creates a <code>CompletionCallbackFactory</code> |
| 246 /// bound to an object. If the constructor is called without an argument, |
| 247 /// the default value of <code>NULL</code> is used. The user then must call |
| 248 /// Initialize() to initialize the object. |
| 249 /// |
| 250 /// param[in] object Optional parameter. An object whose member functions |
| 251 /// are to be bound to CompletionCallbacks created by this |
| 252 /// <code>CompletionCallbackFactory</code>. The default value of this |
| 253 /// parameter is <code>NULL</code>. |
| 254 explicit CompletionCallbackFactory(T* object = NULL) |
| 255 : object_(object) { |
| 256 InitBackPointer(); |
| 257 } |
| 258 |
| 259 /// Destructor. |
| 260 ~CompletionCallbackFactory() { |
| 261 ResetBackPointer(); |
| 262 } |
| 263 |
| 264 /// CancelAll() cancels all <code>CompletionCallbacks</code> allocated from |
| 265 /// this factory. |
| 266 void CancelAll() { |
| 267 ResetBackPointer(); |
| 268 InitBackPointer(); |
| 269 } |
| 270 /// Initialize() binds the <code>CallbackFactory</code> to a particular |
| 271 /// object. Use this when the object is not available at |
| 272 /// <code>CallbackFactory</code> creation, and the <code>NULL</code> default |
| 273 /// is passed to the constructor. The object may only be initialized once, |
| 274 /// either by the constructor, or by a call to Initialize(). |
| 275 /// |
| 276 /// @param[in] object The object whose member functions are to be bound to |
| 277 /// the <code>CompletionCallback</code> created by this |
| 278 /// <code>CompletionCallbackFactory</code>. |
| 279 void Initialize(T* object) { |
| 280 PP_DCHECK(object); |
| 281 PP_DCHECK(!object_); // May only initialize once! |
| 282 object_ = object; |
| 283 } |
| 284 |
| 285 /// GetObject() returns the object that was passed at initialization to |
| 286 /// Intialize(). |
| 287 /// |
| 288 /// @return the object passed to the constructor or Intialize(). |
| 289 T* GetObject() { |
| 290 return object_; |
| 291 } |
| 292 |
| 293 /// NewCallback allocates a new, single-use <code>CompletionCallback</code>. |
| 294 /// The <code>CompletionCallback</code> must be run in order for the memory |
| 295 /// allocated by the methods to be freed. |
| 296 /// NewCallback() is equivalent to NewRequiredCallback() below. |
| 297 /// |
| 298 /// @param[in] method The method to be invoked upon completion of the |
| 299 /// operation. |
| 300 /// |
| 301 /// @return A <code>CompletionCallback</code>. |
| 302 template <typename Method> |
| 303 CompletionCallback NewCallback(Method method) { |
| 304 PP_DCHECK(object_); |
| 305 return NewCallbackHelper(Dispatcher0<Method>(method)); |
| 306 } |
| 307 |
| 308 /// NewRequiredCallback() allocates a new, single-use |
| 309 /// <code>CompletionCallback</code> that will always run. The |
| 310 /// <code>CompletionCallback</code> must be run in order for the memory |
| 311 /// allocated by the methods to be freed. |
| 312 /// |
| 313 /// @param[in] method The method to be invoked upon completion of the |
| 314 /// operation. |
| 315 /// |
| 316 /// @return A <code>CompletionCallback</code>. |
| 317 template <typename Method> |
| 318 CompletionCallback NewRequiredCallback(Method method) { |
| 319 CompletionCallback cc = NewCallback(method); |
| 320 cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); |
| 321 return cc; |
| 322 } |
| 323 |
| 324 /// NewOptionalCallback() allocates a new, single-use |
| 325 /// <code>CompletionCallback</code> that might not run if the method |
| 326 /// taking it can complete synchronously. Thus, if after passing the |
| 327 /// CompletionCallback to a Pepper method, the method does not return |
| 328 /// PP_OK_COMPLETIONPENDING, then you should manually call the |
| 329 /// CompletionCallback's Run method, or memory will be leaked. |
| 330 /// |
| 331 /// @param[in] method The method to be invoked upon completion of the |
| 332 /// operation. |
| 333 /// |
| 334 /// @return A <code>CompletionCallback</code>. |
| 335 template <typename Method> |
| 336 CompletionCallback NewOptionalCallback(Method method) { |
| 337 CompletionCallback cc = NewCallback(method); |
| 338 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); |
| 339 return cc; |
| 340 } |
| 341 |
| 342 /// NewCallback() allocates a new, single-use <code>CompletionCallback</code>. |
| 343 /// The <code>CompletionCallback</code> must be run in order for the memory |
| 344 /// allocated by the methods to be freed. |
| 345 /// NewCallback() is equivalent to NewRequiredCallback() below. |
| 346 /// |
| 347 /// @param[in] method The method to be invoked upon completion of the |
| 348 /// operation. Method should be of type: |
| 349 /// <code>void (T::*)(int32_t result, const A& a)</code> |
| 350 /// |
| 351 /// @param[in] a Passed to <code>method</code> when the completion callback |
| 352 /// runs. |
| 353 /// |
| 354 /// @return A <code>CompletionCallback</code>. |
| 355 template <typename Method, typename A> |
| 356 CompletionCallback NewCallback(Method method, const A& a) { |
| 357 PP_DCHECK(object_); |
| 358 return NewCallbackHelper(Dispatcher1<Method, A>(method, a)); |
| 359 } |
| 360 |
| 361 /// NewRequiredCallback() allocates a new, single-use |
| 362 /// <code>CompletionCallback</code> that will always run. The |
| 363 /// <code>CompletionCallback</code> must be run in order for the memory |
| 364 /// allocated by the methods to be freed. |
| 365 /// |
| 366 /// @param[in] method The method to be invoked upon completion of the |
| 367 /// operation. Method should be of type: |
| 368 /// <code>void (T::*)(int32_t result, const A& a)</code> |
| 369 /// |
| 370 /// @param[in] a Passed to <code>method</code> when the completion callback |
| 371 /// runs. |
| 372 /// |
| 373 /// @return A <code>CompletionCallback</code>. |
| 374 template <typename Method, typename A> |
| 375 CompletionCallback NewRequiredCallback(Method method, const A& a) { |
| 376 CompletionCallback cc = NewCallback(method, a); |
| 377 cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); |
| 378 return cc; |
| 379 } |
| 380 |
| 381 /// NewOptionalCallback() allocates a new, single-use |
| 382 /// <code>CompletionCallback</code> that might not run if the method |
| 383 /// taking it can complete synchronously. Thus, if after passing the |
| 384 /// CompletionCallback to a Pepper method, the method does not return |
| 385 /// PP_OK_COMPLETIONPENDING, then you should manually call the |
| 386 /// CompletionCallback's Run method, or memory will be leaked. |
| 387 /// |
| 388 /// @param[in] method The method to be invoked upon completion of the |
| 389 /// operation. Method should be of type: |
| 390 /// <code>void (T::*)(int32_t result, const A& a)</code> |
| 391 /// |
| 392 /// @param[in] a Passed to <code>method</code> when the completion callback |
| 393 /// runs. |
| 394 /// |
| 395 /// @return A <code>CompletionCallback</code>. |
| 396 template <typename Method, typename A> |
| 397 CompletionCallback NewOptionalCallback(Method method, const A& a) { |
| 398 CompletionCallback cc = NewCallback(method, a); |
| 399 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); |
| 400 return cc; |
| 401 } |
| 402 |
| 403 /// NewCallback() allocates a new, single-use |
| 404 /// <code>CompletionCallback</code>. |
| 405 /// The <code>CompletionCallback</code> must be run in order for the memory |
| 406 /// allocated by the methods to be freed. |
| 407 /// NewCallback() is equivalent to NewRequiredCallback() below. |
| 408 /// |
| 409 /// @param method The method taking the callback. Method should be of type: |
| 410 /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code> |
| 411 /// |
| 412 /// @param[in] a Passed to <code>method</code> when the completion callback |
| 413 /// runs. |
| 414 /// |
| 415 /// @param[in] b Passed to <code>method</code> when the completion callback |
| 416 /// runs. |
| 417 /// |
| 418 /// @return A <code>CompletionCallback</code>. |
| 419 template <typename Method, typename A, typename B> |
| 420 CompletionCallback NewCallback(Method method, const A& a, const B& b) { |
| 421 PP_DCHECK(object_); |
| 422 return NewCallbackHelper(Dispatcher2<Method, A, B>(method, a, b)); |
| 423 } |
| 424 |
| 425 /// NewRequiredCallback() allocates a new, single-use |
| 426 /// <code>CompletionCallback</code> that will always run. The |
| 427 /// <code>CompletionCallback</code> must be run in order for the memory |
| 428 /// allocated by the methods to be freed. |
| 429 /// |
| 430 /// @param method The method taking the callback. Method should be of type: |
| 431 /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code> |
| 432 /// |
| 433 /// @param[in] a Passed to <code>method</code> when the completion callback |
| 434 /// runs. |
| 435 /// |
| 436 /// @param[in] b Passed to <code>method</code> when the completion callback |
| 437 /// runs. |
| 438 /// |
| 439 /// @return A <code>CompletionCallback</code>. |
| 440 template <typename Method, typename A, typename B> |
| 441 CompletionCallback NewRequiredCallback(Method method, const A& a, |
| 442 const B& b) { |
| 443 CompletionCallback cc = NewCallback(method, a, b); |
| 444 cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); |
| 445 return cc; |
| 446 } |
| 447 |
| 448 /// NewOptionalCallback() allocates a new, single-use |
| 449 /// <code>CompletionCallback</code> that might not run if the method |
| 450 /// taking it can complete synchronously. Thus, if after passing the |
| 451 /// CompletionCallback to a Pepper method, the method does not return |
| 452 /// PP_OK_COMPLETIONPENDING, then you should manually call the |
| 453 /// CompletionCallback's Run method, or memory will be leaked. |
| 454 /// |
| 455 /// @param[in] method The method taking the callback. Method should be of |
| 456 /// type: |
| 457 /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code> |
| 458 /// |
| 459 /// @param[in] a Passed to <code>method</code> when the completion callback |
| 460 /// runs. |
| 461 /// |
| 462 /// @param[in] b Passed to <code>method</code> when the completion callback |
| 463 /// runs. |
| 464 /// |
| 465 /// @return A <code>CompletionCallback</code>. |
| 466 template <typename Method, typename A, typename B> |
| 467 CompletionCallback NewOptionalCallback(Method method, const A& a, |
| 468 const B& b) { |
| 469 CompletionCallback cc = NewCallback(method, a, b); |
| 470 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); |
| 471 return cc; |
| 472 } |
| 473 |
| 474 /// NewCallback() allocates a new, single-use |
| 475 /// <code>CompletionCallback</code>. |
| 476 /// The <code>CompletionCallback</code> must be run in order for the memory |
| 477 /// allocated by the methods to be freed. |
| 478 /// NewCallback() is equivalent to NewRequiredCallback() below. |
| 479 /// |
| 480 /// @param method The method taking the callback. Method should be of type: |
| 481 /// <code> |
| 482 /// void (T::*)(int32_t result, const A& a, const B& b, const C& c) |
| 483 /// </code> |
| 484 /// |
| 485 /// @param[in] a Passed to <code>method</code> when the completion callback |
| 486 /// runs. |
| 487 /// |
| 488 /// @param[in] b Passed to <code>method</code> when the completion callback |
| 489 /// runs. |
| 490 /// |
| 491 /// @param[in] c Passed to <code>method</code> when the completion callback |
| 492 /// runs. |
| 493 /// |
| 494 /// @return A <code>CompletionCallback</code>. |
| 495 template <typename Method, typename A, typename B, typename C> |
| 496 CompletionCallback NewCallback(Method method, const A& a, const B& b, |
| 497 const C& c) { |
| 498 PP_DCHECK(object_); |
| 499 return NewCallbackHelper(Dispatcher3<Method, A, B, C>(method, a, b, c)); |
| 500 } |
| 501 |
| 502 /// NewRequiredCallback() allocates a new, single-use |
| 503 /// <code>CompletionCallback</code> that will always run. The |
| 504 /// <code>CompletionCallback</code> must be run in order for the memory |
| 505 /// allocated by the methods to be freed. |
| 506 /// |
| 507 /// @param method The method taking the callback. Method should be of type: |
| 508 /// <code> |
| 509 /// void (T::*)(int32_t result, const A& a, const B& b, const C& c) |
| 510 /// </code> |
| 511 /// |
| 512 /// @param[in] a Passed to <code>method</code> when the completion callback |
| 513 /// runs. |
| 514 /// |
| 515 /// @param[in] b Passed to <code>method</code> when the completion callback |
| 516 /// runs. |
| 517 /// |
| 518 /// @param[in] c Passed to <code>method</code> when the completion callback |
| 519 /// runs. |
| 520 /// |
| 521 /// @return A <code>CompletionCallback</code>. |
| 522 template <typename Method, typename A, typename B, typename C> |
| 523 CompletionCallback NewRequiredCallback(Method method, const A& a, |
| 524 const B& b, const C& c) { |
| 525 CompletionCallback cc = NewCallback(method, a, b, c); |
| 526 cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); |
| 527 return cc; |
| 528 } |
| 529 |
| 530 /// NewOptionalCallback() allocates a new, single-use |
| 531 /// <code>CompletionCallback</code> that might not run if the method |
| 532 /// taking it can complete synchronously. Thus, if after passing the |
| 533 /// CompletionCallback to a Pepper method, the method does not return |
| 534 /// PP_OK_COMPLETIONPENDING, then you should manually call the |
| 535 /// CompletionCallback's Run method, or memory will be leaked. |
| 536 /// |
| 537 /// @param[in] method The method taking the callback. Method should be of |
| 538 /// type: |
| 539 /// <code> |
| 540 /// void (T::*)(int32_t result, const A& a, const B& b, const C& c) |
| 541 /// </code> |
| 542 /// |
| 543 /// @param[in] a Passed to <code>method</code> when the completion callback |
| 544 /// runs. |
| 545 /// |
| 546 /// @param[in] b Passed to <code>method</code> when the completion callback |
| 547 /// runs. |
| 548 /// |
| 549 /// @param[in] c Passed to <code>method</code> when the completion callback |
| 550 /// runs. |
| 551 /// |
| 552 /// @return A <code>CompletionCallback</code>. |
| 553 template <typename Method, typename A, typename B, typename C> |
| 554 CompletionCallback NewOptionalCallback(Method method, const A& a, |
| 555 const B& b, const C& c) { |
| 556 CompletionCallback cc = NewCallback(method, a, b, c); |
| 557 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); |
| 558 return cc; |
| 559 } |
| 560 |
| 561 private: |
| 562 class BackPointer { |
| 563 public: |
| 564 typedef CompletionCallbackFactory<T, RefCount> FactoryType; |
| 565 |
| 566 BackPointer(FactoryType* factory) |
| 567 : factory_(factory) { |
| 568 } |
| 569 |
| 570 void AddRef() { |
| 571 ref_.AddRef(); |
| 572 } |
| 573 |
| 574 void Release() { |
| 575 if (ref_.Release() == 0) |
| 576 delete this; |
| 577 } |
| 578 |
| 579 void DropFactory() { |
| 580 factory_ = NULL; |
| 581 } |
| 582 |
| 583 T* GetObject() { |
| 584 return factory_ ? factory_->GetObject() : NULL; |
| 585 } |
| 586 |
| 587 private: |
| 588 RefCount ref_; |
| 589 FactoryType* factory_; |
| 590 }; |
| 591 |
| 592 template <typename Dispatcher> |
| 593 class CallbackData { |
| 594 public: |
| 595 CallbackData(BackPointer* back_pointer, const Dispatcher& dispatcher) |
| 596 : back_pointer_(back_pointer), |
| 597 dispatcher_(dispatcher) { |
| 598 back_pointer_->AddRef(); |
| 599 } |
| 600 |
| 601 ~CallbackData() { |
| 602 back_pointer_->Release(); |
| 603 } |
| 604 |
| 605 static void Thunk(void* user_data, int32_t result) { |
| 606 Self* self = static_cast<Self*>(user_data); |
| 607 T* object = self->back_pointer_->GetObject(); |
| 608 if (object) |
| 609 self->dispatcher_(object, result); |
| 610 delete self; |
| 611 } |
| 612 |
| 613 private: |
| 614 typedef CallbackData<Dispatcher> Self; |
| 615 BackPointer* back_pointer_; |
| 616 Dispatcher dispatcher_; |
| 617 }; |
| 618 |
| 619 template <typename Method> |
| 620 class Dispatcher0 { |
| 621 public: |
| 622 Dispatcher0(Method method) : method_(method) { |
| 623 } |
| 624 void operator()(T* object, int32_t result) { |
| 625 (object->*method_)(result); |
| 626 } |
| 627 private: |
| 628 Method method_; |
| 629 }; |
| 630 |
| 631 template <typename Method, typename A> |
| 632 class Dispatcher1 { |
| 633 public: |
| 634 Dispatcher1(Method method, const A& a) |
| 635 : method_(method), |
| 636 a_(a) { |
| 637 } |
| 638 void operator()(T* object, int32_t result) { |
| 639 (object->*method_)(result, a_); |
| 640 } |
| 641 private: |
| 642 Method method_; |
| 643 A a_; |
| 644 }; |
| 645 |
| 646 template <typename Method, typename A, typename B> |
| 647 class Dispatcher2 { |
| 648 public: |
| 649 Dispatcher2(Method method, const A& a, const B& b) |
| 650 : method_(method), |
| 651 a_(a), |
| 652 b_(b) { |
| 653 } |
| 654 void operator()(T* object, int32_t result) { |
| 655 (object->*method_)(result, a_, b_); |
| 656 } |
| 657 private: |
| 658 Method method_; |
| 659 A a_; |
| 660 B b_; |
| 661 }; |
| 662 |
| 663 template <typename Method, typename A, typename B, typename C> |
| 664 class Dispatcher3 { |
| 665 public: |
| 666 Dispatcher3(Method method, const A& a, const B& b, const C& c) |
| 667 : method_(method), |
| 668 a_(a), |
| 669 b_(b), |
| 670 c_(c) { |
| 671 } |
| 672 void operator()(T* object, int32_t result) { |
| 673 (object->*method_)(result, a_, b_, c_); |
| 674 } |
| 675 private: |
| 676 Method method_; |
| 677 A a_; |
| 678 B b_; |
| 679 C c_; |
| 680 }; |
| 681 |
| 682 void InitBackPointer() { |
| 683 back_pointer_ = new BackPointer(this); |
| 684 back_pointer_->AddRef(); |
| 685 } |
| 686 |
| 687 void ResetBackPointer() { |
| 688 back_pointer_->DropFactory(); |
| 689 back_pointer_->Release(); |
| 690 } |
| 691 |
| 692 template <typename Dispatcher> |
| 693 CompletionCallback NewCallbackHelper(const Dispatcher& dispatcher) { |
| 694 PP_DCHECK(object_); // Expects a non-null object! |
| 695 return CompletionCallback( |
| 696 &CallbackData<Dispatcher>::Thunk, |
| 697 new CallbackData<Dispatcher>(back_pointer_, dispatcher)); |
| 698 } |
| 699 |
| 700 // Disallowed: |
| 701 CompletionCallbackFactory(const CompletionCallbackFactory&); |
| 702 CompletionCallbackFactory& operator=(const CompletionCallbackFactory&); |
| 703 |
| 704 T* object_; |
| 705 BackPointer* back_pointer_; |
| 706 }; |
| 707 |
159 } // namespace pp | 708 } // namespace pp |
160 | 709 |
161 #endif // PPAPI_CPP_COMPLETION_CALLBACK_H_ | 710 #endif // PPAPI_CPP_COMPLETION_CALLBACK_H_ |
OLD | NEW |