• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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