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.
14namespace pp {
15
16// TypeUnwrapper --------------------------------------------------------------
17
18namespace 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.
23template <typename T> struct TypeUnwrapper {
24  typedef T StorageType;
25};
26template <typename T> struct TypeUnwrapper<T&> {
27  typedef T StorageType;
28};
29template <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.
188template <typename T, typename ThreadTraits = ThreadSafeThreadTraits>
189class 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