| OLD | NEW |
| (Empty) |
| 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 | |
| 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/non_thread_safe_ref_count.h" | |
| 10 | |
| 11 namespace pp { | |
| 12 | |
| 13 /// CompletionCallbackFactory<T> may be used to create CompletionCallback | |
| 14 /// objects that are bound to member functions. | |
| 15 /// | |
| 16 /// If a factory is destroyed, then any pending callbacks will be cancelled | |
| 17 /// preventing any bound member functions from being called. The CancelAll() | |
| 18 /// method allows pending callbacks to be cancelled without destroying the | |
| 19 /// factory. | |
| 20 /// | |
| 21 /// <strong>Note: </strong><code>CompletionCallbackFactory<T></code> isn't | |
| 22 /// thread safe, but you can make it more thread-friendly by passing a | |
| 23 /// thread-safe refcounting class as the second template element. However, it | |
| 24 /// only guarantees safety for creating a callback from another thread, the | |
| 25 /// callback itself needs to execute on the same thread as the thread that | |
| 26 /// creates/destroys the factory. With this restriction, it is safe to create | |
| 27 /// the <code>CompletionCallbackFactory</code> on the main thread, create | |
| 28 /// callbacks from any thread and pass them to CallOnMainThread(). | |
| 29 /// | |
| 30 /// <strong>Example: </strong> | |
| 31 /// | |
| 32 /// @code | |
| 33 /// | |
| 34 /// class MyHandler { | |
| 35 /// public: | |
| 36 /// // If an compiler warns on following using |this| in the initializer | |
| 37 /// // list, use PP_ALLOW_THIS_IN_INITIALIZER_LIST macro. | |
| 38 /// MyHandler() : factory_(this), offset_(0) { | |
| 39 /// } | |
| 40 /// | |
| 41 /// void ProcessFile(const FileRef& file) { | |
| 42 /// CompletionCallback cc = factory_.NewRequiredCallback( | |
| 43 /// &MyHandler::DidOpen); | |
| 44 /// int32_t rv = fio_.Open(file, PP_FileOpenFlag_Read, cc); | |
| 45 /// CHECK(rv == PP_OK_COMPLETIONPENDING); | |
| 46 /// } | |
| 47 /// | |
| 48 /// private: | |
| 49 /// CompletionCallback NewCallback() { | |
| 50 /// return factory_.NewCallback(&MyHandler::DidCompleteIO); | |
| 51 /// } | |
| 52 /// | |
| 53 /// void DidOpen(int32_t result) { | |
| 54 /// if (result == PP_OK) { | |
| 55 /// // The file is open, and we can begin reading. | |
| 56 /// offset_ = 0; | |
| 57 /// ReadMore(); | |
| 58 /// } else { | |
| 59 /// // Failed to open the file with error given by 'result'. | |
| 60 /// } | |
| 61 /// } | |
| 62 /// | |
| 63 /// void DidRead(int32_t result) { | |
| 64 /// if (result > 0) { | |
| 65 /// // buf_ now contains 'result' number of bytes from the file. | |
| 66 /// ProcessBytes(buf_, result); | |
| 67 /// offset_ += result; | |
| 68 /// ReadMore(); | |
| 69 /// } else { | |
| 70 /// // Done reading (possibly with an error given by 'result'). | |
| 71 /// } | |
| 72 /// } | |
| 73 /// | |
| 74 /// void ReadMore() { | |
| 75 /// CompletionCallback cc = | |
| 76 /// factory_.NewOptionalCallback(&MyHandler::DidRead); | |
| 77 /// int32_t rv = fio_.Read(offset_, buf_, sizeof(buf_), | |
| 78 /// cc.pp_completion_callback()); | |
| 79 /// if (rv != PP_OK_COMPLETIONPENDING) | |
| 80 /// cc.Run(rv); | |
| 81 /// } | |
| 82 /// | |
| 83 /// void ProcessBytes(const char* bytes, int32_t length) { | |
| 84 /// // Do work ... | |
| 85 /// } | |
| 86 /// | |
| 87 /// pp::CompletionCallbackFactory<MyHandler> factory_; | |
| 88 /// pp::FileIO fio_; | |
| 89 /// char buf_[4096]; | |
| 90 /// int64_t offset_; | |
| 91 /// }; | |
| 92 /// | |
| 93 /// @endcode | |
| 94 /// | |
| 95 template <typename T, typename RefCount = NonThreadSafeRefCount> | |
| 96 class CompletionCallbackFactory { | |
| 97 public: | |
| 98 | |
| 99 /// This constructor creates a <code>CompletionCallbackFactory</code> | |
| 100 /// bound to an object. If the constructor is called without an argument, | |
| 101 /// the default value of <code>NULL</code> is used. The user then must call | |
| 102 /// Initialize() to initialize the object. | |
| 103 /// | |
| 104 /// param[in] object Optional parameter. An object whose member functions | |
| 105 /// are to be bound to CompletionCallbacks created by this | |
| 106 /// <code>CompletionCallbackFactory</code>. The default value of this | |
| 107 /// parameter is <code>NULL</code>. | |
| 108 explicit CompletionCallbackFactory(T* object = NULL) | |
| 109 : object_(object) { | |
| 110 InitBackPointer(); | |
| 111 } | |
| 112 | |
| 113 /// Destructor. | |
| 114 ~CompletionCallbackFactory() { | |
| 115 ResetBackPointer(); | |
| 116 } | |
| 117 | |
| 118 /// CancelAll() cancels all <code>CompletionCallbacks</code> allocated from | |
| 119 /// this factory. | |
| 120 void CancelAll() { | |
| 121 ResetBackPointer(); | |
| 122 InitBackPointer(); | |
| 123 } | |
| 124 /// Initialize() binds the <code>CallbackFactory</code> to a particular | |
| 125 /// object. Use this when the object is not available at | |
| 126 /// <code>CallbackFactory</code> creation, and the <code>NULL</code> default | |
| 127 /// is passed to the constructor. The object may only be initialized once, | |
| 128 /// either by the constructor, or by a call to Initialize(). | |
| 129 /// | |
| 130 /// @param[in] object The object whose member functions are to be bound to | |
| 131 /// the <code>CompletionCallback</code> created by this | |
| 132 /// <code>CompletionCallbackFactory</code>. | |
| 133 void Initialize(T* object) { | |
| 134 PP_DCHECK(object); | |
| 135 PP_DCHECK(!object_); // May only initialize once! | |
| 136 object_ = object; | |
| 137 } | |
| 138 | |
| 139 /// GetObject() returns the object that was passed at initialization to | |
| 140 /// Intialize(). | |
| 141 /// | |
| 142 /// @return the object passed to the constructor or Intialize(). | |
| 143 T* GetObject() { | |
| 144 return object_; | |
| 145 } | |
| 146 | |
| 147 /// NewCallback allocates a new, single-use <code>CompletionCallback</code>. | |
| 148 /// The <code>CompletionCallback</code> must be run in order for the memory | |
| 149 /// allocated by the methods to be freed. | |
| 150 /// NewCallback() is equivalent to NewRequiredCallback() below. | |
| 151 /// | |
| 152 /// @param[in] method The method to be invoked upon completion of the | |
| 153 /// operation. | |
| 154 /// | |
| 155 /// @return A <code>CompletionCallback</code>. | |
| 156 template <typename Method> | |
| 157 CompletionCallback NewCallback(Method method) { | |
| 158 PP_DCHECK(object_); | |
| 159 return NewCallbackHelper(Dispatcher0<Method>(method)); | |
| 160 } | |
| 161 | |
| 162 /// NewRequiredCallback() allocates a new, single-use | |
| 163 /// <code>CompletionCallback</code> that will always run. The | |
| 164 /// <code>CompletionCallback</code> must be run in order for the memory | |
| 165 /// allocated by the methods to be freed. | |
| 166 /// | |
| 167 /// @param[in] method The method to be invoked upon completion of the | |
| 168 /// operation. | |
| 169 /// | |
| 170 /// @return A <code>CompletionCallback</code>. | |
| 171 template <typename Method> | |
| 172 CompletionCallback NewRequiredCallback(Method method) { | |
| 173 CompletionCallback cc = NewCallback(method); | |
| 174 cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); | |
| 175 return cc; | |
| 176 } | |
| 177 | |
| 178 /// NewOptionalCallback() allocates a new, single-use | |
| 179 /// <code>CompletionCallback</code> that might not run if the method | |
| 180 /// taking it can complete synchronously. Thus, if after passing the | |
| 181 /// CompletionCallback to a Pepper method, the method does not return | |
| 182 /// PP_OK_COMPLETIONPENDING, then you should manually call the | |
| 183 /// CompletionCallback's Run method, or memory will be leaked. | |
| 184 /// | |
| 185 /// @param[in] method The method to be invoked upon completion of the | |
| 186 /// operation. | |
| 187 /// | |
| 188 /// @return A <code>CompletionCallback</code>. | |
| 189 template <typename Method> | |
| 190 CompletionCallback NewOptionalCallback(Method method) { | |
| 191 CompletionCallback cc = NewCallback(method); | |
| 192 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); | |
| 193 return cc; | |
| 194 } | |
| 195 | |
| 196 /// NewCallback() allocates a new, single-use <code>CompletionCallback</code>. | |
| 197 /// The <code>CompletionCallback</code> must be run in order for the memory | |
| 198 /// allocated by the methods to be freed. | |
| 199 /// NewCallback() is equivalent to NewRequiredCallback() below. | |
| 200 /// | |
| 201 /// @param[in] method The method to be invoked upon completion of the | |
| 202 /// operation. Method should be of type: | |
| 203 /// <code>void (T::*)(int32_t result, const A& a)</code> | |
| 204 /// | |
| 205 /// @param[in] a Passed to <code>method</code> when the completion callback | |
| 206 /// runs. | |
| 207 /// | |
| 208 /// @return A <code>CompletionCallback</code>. | |
| 209 template <typename Method, typename A> | |
| 210 CompletionCallback NewCallback(Method method, const A& a) { | |
| 211 PP_DCHECK(object_); | |
| 212 return NewCallbackHelper(Dispatcher1<Method, A>(method, a)); | |
| 213 } | |
| 214 | |
| 215 /// NewRequiredCallback() allocates a new, single-use | |
| 216 /// <code>CompletionCallback</code> that will always run. The | |
| 217 /// <code>CompletionCallback</code> must be run in order for the memory | |
| 218 /// allocated by the methods to be freed. | |
| 219 /// | |
| 220 /// @param[in] method The method to be invoked upon completion of the | |
| 221 /// operation. Method should be of type: | |
| 222 /// <code>void (T::*)(int32_t result, const A& a)</code> | |
| 223 /// | |
| 224 /// @param[in] a Passed to <code>method</code> when the completion callback | |
| 225 /// runs. | |
| 226 /// | |
| 227 /// @return A <code>CompletionCallback</code>. | |
| 228 template <typename Method, typename A> | |
| 229 CompletionCallback NewRequiredCallback(Method method, const A& a) { | |
| 230 CompletionCallback cc = NewCallback(method, a); | |
| 231 cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); | |
| 232 return cc; | |
| 233 } | |
| 234 | |
| 235 /// NewOptionalCallback() allocates a new, single-use | |
| 236 /// <code>CompletionCallback</code> that might not run if the method | |
| 237 /// taking it can complete synchronously. Thus, if after passing the | |
| 238 /// CompletionCallback to a Pepper method, the method does not return | |
| 239 /// PP_OK_COMPLETIONPENDING, then you should manually call the | |
| 240 /// CompletionCallback's Run method, or memory will be leaked. | |
| 241 /// | |
| 242 /// @param[in] method The method to be invoked upon completion of the | |
| 243 /// operation. Method should be of type: | |
| 244 /// <code>void (T::*)(int32_t result, const A& a)</code> | |
| 245 /// | |
| 246 /// @param[in] a Passed to <code>method</code> when the completion callback | |
| 247 /// runs. | |
| 248 /// | |
| 249 /// @return A <code>CompletionCallback</code>. | |
| 250 template <typename Method, typename A> | |
| 251 CompletionCallback NewOptionalCallback(Method method, const A& a) { | |
| 252 CompletionCallback cc = NewCallback(method, a); | |
| 253 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); | |
| 254 return cc; | |
| 255 } | |
| 256 | |
| 257 /// NewCallback() allocates a new, single-use | |
| 258 /// <code>CompletionCallback</code>. | |
| 259 /// The <code>CompletionCallback</code> must be run in order for the memory | |
| 260 /// allocated by the methods to be freed. | |
| 261 /// NewCallback() is equivalent to NewRequiredCallback() below. | |
| 262 /// | |
| 263 /// @param method The method taking the callback. Method should be of type: | |
| 264 /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code> | |
| 265 /// | |
| 266 /// @param[in] a Passed to <code>method</code> when the completion callback | |
| 267 /// runs. | |
| 268 /// | |
| 269 /// @param[in] b Passed to <code>method</code> when the completion callback | |
| 270 /// runs. | |
| 271 /// | |
| 272 /// @return A <code>CompletionCallback</code>. | |
| 273 template <typename Method, typename A, typename B> | |
| 274 CompletionCallback NewCallback(Method method, const A& a, const B& b) { | |
| 275 PP_DCHECK(object_); | |
| 276 return NewCallbackHelper(Dispatcher2<Method, A, B>(method, a, b)); | |
| 277 } | |
| 278 | |
| 279 /// NewRequiredCallback() allocates a new, single-use | |
| 280 /// <code>CompletionCallback</code> that will always run. The | |
| 281 /// <code>CompletionCallback</code> must be run in order for the memory | |
| 282 /// allocated by the methods to be freed. | |
| 283 /// | |
| 284 /// @param method The method taking the callback. Method should be of type: | |
| 285 /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code> | |
| 286 /// | |
| 287 /// @param[in] a Passed to <code>method</code> when the completion callback | |
| 288 /// runs. | |
| 289 /// | |
| 290 /// @param[in] b Passed to <code>method</code> when the completion callback | |
| 291 /// runs. | |
| 292 /// | |
| 293 /// @return A <code>CompletionCallback</code>. | |
| 294 template <typename Method, typename A, typename B> | |
| 295 CompletionCallback NewRequiredCallback(Method method, const A& a, | |
| 296 const B& b) { | |
| 297 CompletionCallback cc = NewCallback(method, a, b); | |
| 298 cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); | |
| 299 return cc; | |
| 300 } | |
| 301 | |
| 302 /// NewOptionalCallback() allocates a new, single-use | |
| 303 /// <code>CompletionCallback</code> that might not run if the method | |
| 304 /// taking it can complete synchronously. Thus, if after passing the | |
| 305 /// CompletionCallback to a Pepper method, the method does not return | |
| 306 /// PP_OK_COMPLETIONPENDING, then you should manually call the | |
| 307 /// CompletionCallback's Run method, or memory will be leaked. | |
| 308 /// | |
| 309 /// @param[in] method The method taking the callback. Method should be of | |
| 310 /// type: | |
| 311 /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code> | |
| 312 /// | |
| 313 /// @param[in] a Passed to <code>method</code> when the completion callback | |
| 314 /// runs. | |
| 315 /// | |
| 316 /// @param[in] b Passed to <code>method</code> when the completion callback | |
| 317 /// runs. | |
| 318 /// | |
| 319 /// @return A <code>CompletionCallback</code>. | |
| 320 template <typename Method, typename A, typename B> | |
| 321 CompletionCallback NewOptionalCallback(Method method, const A& a, | |
| 322 const B& b) { | |
| 323 CompletionCallback cc = NewCallback(method, a, b); | |
| 324 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); | |
| 325 return cc; | |
| 326 } | |
| 327 | |
| 328 /// NewCallback() allocates a new, single-use | |
| 329 /// <code>CompletionCallback</code>. | |
| 330 /// The <code>CompletionCallback</code> must be run in order for the memory | |
| 331 /// allocated by the methods to be freed. | |
| 332 /// NewCallback() is equivalent to NewRequiredCallback() below. | |
| 333 /// | |
| 334 /// @param method The method taking the callback. Method should be of type: | |
| 335 /// <code> | |
| 336 /// void (T::*)(int32_t result, const A& a, const B& b, const C& c) | |
| 337 /// </code> | |
| 338 /// | |
| 339 /// @param[in] a Passed to <code>method</code> when the completion callback | |
| 340 /// runs. | |
| 341 /// | |
| 342 /// @param[in] b Passed to <code>method</code> when the completion callback | |
| 343 /// runs. | |
| 344 /// | |
| 345 /// @param[in] c Passed to <code>method</code> when the completion callback | |
| 346 /// runs. | |
| 347 /// | |
| 348 /// @return A <code>CompletionCallback</code>. | |
| 349 template <typename Method, typename A, typename B, typename C> | |
| 350 CompletionCallback NewCallback(Method method, const A& a, const B& b, | |
| 351 const C& c) { | |
| 352 PP_DCHECK(object_); | |
| 353 return NewCallbackHelper(Dispatcher3<Method, A, B, C>(method, a, b, c)); | |
| 354 } | |
| 355 | |
| 356 /// NewRequiredCallback() allocates a new, single-use | |
| 357 /// <code>CompletionCallback</code> that will always run. The | |
| 358 /// <code>CompletionCallback</code> must be run in order for the memory | |
| 359 /// allocated by the methods to be freed. | |
| 360 /// | |
| 361 /// @param method The method taking the callback. Method should be of type: | |
| 362 /// <code> | |
| 363 /// void (T::*)(int32_t result, const A& a, const B& b, const C& c) | |
| 364 /// </code> | |
| 365 /// | |
| 366 /// @param[in] a Passed to <code>method</code> when the completion callback | |
| 367 /// runs. | |
| 368 /// | |
| 369 /// @param[in] b Passed to <code>method</code> when the completion callback | |
| 370 /// runs. | |
| 371 /// | |
| 372 /// @param[in] c Passed to <code>method</code> when the completion callback | |
| 373 /// runs. | |
| 374 /// | |
| 375 /// @return A <code>CompletionCallback</code>. | |
| 376 template <typename Method, typename A, typename B, typename C> | |
| 377 CompletionCallback NewRequiredCallback(Method method, const A& a, | |
| 378 const B& b, const C& c) { | |
| 379 CompletionCallback cc = NewCallback(method, a, b, c); | |
| 380 cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); | |
| 381 return cc; | |
| 382 } | |
| 383 | |
| 384 /// NewOptionalCallback() allocates a new, single-use | |
| 385 /// <code>CompletionCallback</code> that might not run if the method | |
| 386 /// taking it can complete synchronously. Thus, if after passing the | |
| 387 /// CompletionCallback to a Pepper method, the method does not return | |
| 388 /// PP_OK_COMPLETIONPENDING, then you should manually call the | |
| 389 /// CompletionCallback's Run method, or memory will be leaked. | |
| 390 /// | |
| 391 /// @param[in] method The method taking the callback. Method should be of | |
| 392 /// type: | |
| 393 /// <code> | |
| 394 /// void (T::*)(int32_t result, const A& a, const B& b, const C& c) | |
| 395 /// </code> | |
| 396 /// | |
| 397 /// @param[in] a Passed to <code>method</code> when the completion callback | |
| 398 /// runs. | |
| 399 /// | |
| 400 /// @param[in] b Passed to <code>method</code> when the completion callback | |
| 401 /// runs. | |
| 402 /// | |
| 403 /// @param[in] c Passed to <code>method</code> when the completion callback | |
| 404 /// runs. | |
| 405 /// | |
| 406 /// @return A <code>CompletionCallback</code>. | |
| 407 template <typename Method, typename A, typename B, typename C> | |
| 408 CompletionCallback NewOptionalCallback(Method method, const A& a, | |
| 409 const B& b, const C& c) { | |
| 410 CompletionCallback cc = NewCallback(method, a, b, c); | |
| 411 cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); | |
| 412 return cc; | |
| 413 } | |
| 414 | |
| 415 private: | |
| 416 class BackPointer { | |
| 417 public: | |
| 418 typedef CompletionCallbackFactory<T, RefCount> FactoryType; | |
| 419 | |
| 420 BackPointer(FactoryType* factory) | |
| 421 : factory_(factory) { | |
| 422 } | |
| 423 | |
| 424 void AddRef() { | |
| 425 ref_.AddRef(); | |
| 426 } | |
| 427 | |
| 428 void Release() { | |
| 429 if (ref_.Release() == 0) | |
| 430 delete this; | |
| 431 } | |
| 432 | |
| 433 void DropFactory() { | |
| 434 factory_ = NULL; | |
| 435 } | |
| 436 | |
| 437 T* GetObject() { | |
| 438 return factory_ ? factory_->GetObject() : NULL; | |
| 439 } | |
| 440 | |
| 441 private: | |
| 442 RefCount ref_; | |
| 443 FactoryType* factory_; | |
| 444 }; | |
| 445 | |
| 446 template <typename Dispatcher> | |
| 447 class CallbackData { | |
| 448 public: | |
| 449 CallbackData(BackPointer* back_pointer, const Dispatcher& dispatcher) | |
| 450 : back_pointer_(back_pointer), | |
| 451 dispatcher_(dispatcher) { | |
| 452 back_pointer_->AddRef(); | |
| 453 } | |
| 454 | |
| 455 ~CallbackData() { | |
| 456 back_pointer_->Release(); | |
| 457 } | |
| 458 | |
| 459 static void Thunk(void* user_data, int32_t result) { | |
| 460 Self* self = static_cast<Self*>(user_data); | |
| 461 T* object = self->back_pointer_->GetObject(); | |
| 462 if (object) | |
| 463 self->dispatcher_(object, result); | |
| 464 delete self; | |
| 465 } | |
| 466 | |
| 467 private: | |
| 468 typedef CallbackData<Dispatcher> Self; | |
| 469 BackPointer* back_pointer_; | |
| 470 Dispatcher dispatcher_; | |
| 471 }; | |
| 472 | |
| 473 template <typename Method> | |
| 474 class Dispatcher0 { | |
| 475 public: | |
| 476 Dispatcher0(Method method) : method_(method) { | |
| 477 } | |
| 478 void operator()(T* object, int32_t result) { | |
| 479 (object->*method_)(result); | |
| 480 } | |
| 481 private: | |
| 482 Method method_; | |
| 483 }; | |
| 484 | |
| 485 template <typename Method, typename A> | |
| 486 class Dispatcher1 { | |
| 487 public: | |
| 488 Dispatcher1(Method method, const A& a) | |
| 489 : method_(method), | |
| 490 a_(a) { | |
| 491 } | |
| 492 void operator()(T* object, int32_t result) { | |
| 493 (object->*method_)(result, a_); | |
| 494 } | |
| 495 private: | |
| 496 Method method_; | |
| 497 A a_; | |
| 498 }; | |
| 499 | |
| 500 template <typename Method, typename A, typename B> | |
| 501 class Dispatcher2 { | |
| 502 public: | |
| 503 Dispatcher2(Method method, const A& a, const B& b) | |
| 504 : method_(method), | |
| 505 a_(a), | |
| 506 b_(b) { | |
| 507 } | |
| 508 void operator()(T* object, int32_t result) { | |
| 509 (object->*method_)(result, a_, b_); | |
| 510 } | |
| 511 private: | |
| 512 Method method_; | |
| 513 A a_; | |
| 514 B b_; | |
| 515 }; | |
| 516 | |
| 517 template <typename Method, typename A, typename B, typename C> | |
| 518 class Dispatcher3 { | |
| 519 public: | |
| 520 Dispatcher3(Method method, const A& a, const B& b, const C& c) | |
| 521 : method_(method), | |
| 522 a_(a), | |
| 523 b_(b), | |
| 524 c_(c) { | |
| 525 } | |
| 526 void operator()(T* object, int32_t result) { | |
| 527 (object->*method_)(result, a_, b_, c_); | |
| 528 } | |
| 529 private: | |
| 530 Method method_; | |
| 531 A a_; | |
| 532 B b_; | |
| 533 C c_; | |
| 534 }; | |
| 535 | |
| 536 void InitBackPointer() { | |
| 537 back_pointer_ = new BackPointer(this); | |
| 538 back_pointer_->AddRef(); | |
| 539 } | |
| 540 | |
| 541 void ResetBackPointer() { | |
| 542 back_pointer_->DropFactory(); | |
| 543 back_pointer_->Release(); | |
| 544 } | |
| 545 | |
| 546 template <typename Dispatcher> | |
| 547 CompletionCallback NewCallbackHelper(const Dispatcher& dispatcher) { | |
| 548 PP_DCHECK(object_); // Expects a non-null object! | |
| 549 return CompletionCallback( | |
| 550 &CallbackData<Dispatcher>::Thunk, | |
| 551 new CallbackData<Dispatcher>(back_pointer_, dispatcher)); | |
| 552 } | |
| 553 | |
| 554 // Disallowed: | |
| 555 CompletionCallbackFactory(const CompletionCallbackFactory&); | |
| 556 CompletionCallbackFactory& operator=(const CompletionCallbackFactory&); | |
| 557 | |
| 558 T* object_; | |
| 559 BackPointer* back_pointer_; | |
| 560 }; | |
| 561 | |
| 562 } // namespace pp | |
| 563 | |
| 564 #endif // PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_ | |
| OLD | NEW |