15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/completion_callback.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/utility/completion_callback_factory_thread_traits.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// @file
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// This file defines the API to create CompletionCallback objects that are
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// bound to member functions.
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace pp {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TypeUnwrapper --------------------------------------------------------------
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace internal {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The TypeUnwrapper converts references and const references to the
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// underlying type used for storage and passing as an argument. It is for
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// internal use only.
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename T> struct TypeUnwrapper {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef T StorageType;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename T> struct TypeUnwrapper<T&> {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef T StorageType;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename T> struct TypeUnwrapper<const T&> {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef T StorageType;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace internal
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ----------------------------------------------------------------------------
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// CompletionCallbackFactory<T> may be used to create CompletionCallback
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// objects that are bound to member functions.
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// If a factory is destroyed, then any pending callbacks will be cancelled
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// preventing any bound member functions from being called.  The CancelAll()
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// method allows pending callbacks to be cancelled without destroying the
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// factory.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// <strong>Note: </strong><code>CompletionCallbackFactory<T></code> isn't
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// thread safe, but it is somewhat thread-friendly when used with a
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// thread-safe traits class as the second template element. However, it
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// only guarantees safety for creating a callback from another thread, the
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// callback itself needs to execute on the same thread as the thread that
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// creates/destroys the factory. With this restriction, it is safe to create
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// the <code>CompletionCallbackFactory</code> on the main thread, create
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// callbacks from any thread and pass them to CallOnMainThread().
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// <strong>Example: </strong>
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// @code
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///   class MyClass {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///    public:
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///     // If an compiler warns on following using |this| in the initializer
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///     // list, use PP_ALLOW_THIS_IN_INITIALIZER_LIST macro.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///     MyClass() : factory_(this) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///     }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///     void OpenFile(const pp::FileRef& file) {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///       pp::CompletionCallback cc = factory_.NewCallback(&MyClass::DidOpen);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///       int32_t rv = file_io_.Open(file, PP_FileOpenFlag_Read, cc);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///       CHECK(rv == PP_OK_COMPLETIONPENDING);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///     }
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///    private:
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///     void DidOpen(int32_t result) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///       if (result == PP_OK) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///         // The file is open, and we can begin reading.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///         // ...
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///       } else {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///         // Failed to open the file with error given by 'result'.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///       }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///     }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///     pp::CompletionCallbackFactory<MyClass> factory_;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///   };
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// @endcode
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// <strong>Passing additional parameters to your callback</strong>
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// As a convenience, the <code>CompletionCallbackFactory</code> can optionally
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// create a closure with up to three bound parameters that it will pass to
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// your callback function. This can be useful for passing information about
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// the request to your callback function, which is especially useful if your
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// class has multiple asynchronous callbacks pending.
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// For the above example, of opening a file, let's say you want to keep some
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// description associated with your request, you might implement your OpenFile
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// and DidOpen callback as follows:
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// @code
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///   void OpenFile(const pp::FileRef& file) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///     std::string message = "Opening file!";
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///     pp::CompletionCallback cc = factory_.NewCallback(&MyClass::DidOpen,
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///                                                      message);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///     int32_t rv = file_io_.Open(file, PP_FileOpenFlag_Read, cc);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///     CHECK(rv == PP_OK_COMPLETIONPENDING);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///   }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///   void DidOpen(int32_t result, const std::string& message) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///     // "message" will be "Opening file!".
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///     ...
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///   }
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// @endcode
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// <strong>Optional versus required callbacks</strong>
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// When you create an "optional" callback, the browser may return the results
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// synchronously if they are available. This can allow for higher performance
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// in some cases if data is available quickly (for example, for network loads
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// where there may be a lot of data coming quickly). In this case, the
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// callback will never be run.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// When creating a new callback with the factory, there will be data allocated
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// on the heap that tracks the callback information and any bound arguments.
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// This data is freed when the callback executes. In the case of optional
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// callbacks, since the browser will never issue the callback, the internal
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// tracking data will be leaked.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// Therefore, if you use optional callbacks, it's important to manually
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// issue the callback to free up this data. The typical pattern is:
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// @code
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///   pp::CompletionCallback callback = callback_factory.NewOptionalCallback(
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///       &MyClass::OnDataReady);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///   int32_t result = interface->GetData(callback);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///   if (result != PP_OK_COMPLETIONPENDING)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///      callback.Run(result);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// @endcode
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// Because of this additional complexity, it's generally recommended that
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// you not use optional callbacks except when performance is more important
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// (such as loading large resources from the network). In most other cases,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// the performance difference will not be worth the additional complexity,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// and most functions may never actually have the ability to complete
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// synchronously.
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// <strong>Completion callbacks with output</strong>
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// For some API calls, the browser returns data to the caller via an output
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// parameter. These can be difficult to manage since the output parameter
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// must remain valid for as long as the callback is pending. Note also that
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// CancelAll (or destroying the callback factory) does <i>not</i> cancel the
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// callback from the browser's perspective, only the execution of the callback
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// in the plugin code, and the output parameter will still be written to!
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// This means that you can't use class members as output parameters without
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// risking crashes.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// To make this case easier, the CompletionCallbackFactory can allocate and
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// manage the output data for you and pass it to your callback function. This
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// makes such calls more natural and less error-prone.
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// To create such a callback, use NewCallbackWithOutput and specify a callback
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// function that takes the output parameter as its second argument. Let's say
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// you're calling a function GetFile which asynchronously returns a
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// pp::FileRef. GetFile's signature will be <code>int32_t GetFile(const
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// CompletionCallbackWithOutput<pp::FileRef>& callback);</code> and your
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// calling code would look like this:
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// @code
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///   void RequestFile() {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///     file_interface->GetFile(callback_factory_.NewCallbackWithOutput(
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///         &MyClass::GotFile));
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///   }
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///   void GotFile(int32_t result, const pp::FileRef& file) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///     if (result == PP_OK) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///       ...use file...
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///     } else {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///       ...handle error...
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///     }
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///   }
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// @endcode
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// As with regular completion callbacks, you can optionally add up to three
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// bound arguments. These are passed following the output argument.
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// Your callback may take the output argument as a copy (common for small
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// types like integers, a const reference (common for structures and
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// resources to avoid an extra copy), or as a non-const reference. One
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// optimization you can do if your callback function may take large arrays
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// is to accept your output argument as a non-const reference and to swap()
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// the argument with a vector of your own to store it. This means you don't
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// have to copy the buffer to consume it.
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename T, typename ThreadTraits = ThreadSafeThreadTraits>
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CompletionCallbackFactory {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// This constructor creates a <code>CompletionCallbackFactory</code>
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// bound to an object. If the constructor is called without an argument,
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// the default value of <code>NULL</code> is used. The user then must call
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// Initialize() to initialize the object.
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// param[in] object Optional parameter. An object whose member functions
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// are to be bound to CompletionCallbacks created by this
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// <code>CompletionCallbackFactory</code>. The default value of this
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// parameter is <code>NULL</code>.
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit CompletionCallbackFactory(T* object = NULL)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : object_(object) {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Assume that we don't need to lock since construction should be complete
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // before the pointer is used on another thread.
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitBackPointer();
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// Destructor.
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~CompletionCallbackFactory() {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Assume that we don't need to lock since this object should not be used
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // from multiple threads during destruction.
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResetBackPointer();
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// CancelAll() cancels all <code>CompletionCallbacks</code> allocated from
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// this factory.
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CancelAll() {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typename ThreadTraits::AutoLock lock(lock_);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResetBackPointer();
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitBackPointer();
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// Initialize() binds the <code>CallbackFactory</code> to a particular
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// object. Use this when the object is not available at
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// <code>CallbackFactory</code> creation, and the <code>NULL</code> default
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// is passed to the constructor. The object may only be initialized once,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// either by the constructor, or by a call to Initialize().
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// This class may not be used on any thread until initialization is complete.
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param[in] object The object whose member functions are to be bound to
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// the <code>CompletionCallback</code> created by this
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// <code>CompletionCallbackFactory</code>.
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Initialize(T* object) {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_DCHECK(object);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_DCHECK(!object_);  // May only initialize once!
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    object_ = object;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// GetObject() returns the object that was passed at initialization to
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// Intialize().
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @return the object passed to the constructor or Intialize().
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  T* GetObject() {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return object_;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// NewCallback allocates a new, single-use <code>CompletionCallback</code>.
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// The <code>CompletionCallback</code> must be run in order for the memory
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// allocated by the methods to be freed.
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param[in] method The method to be invoked upon completion of the
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// operation.
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @return A <code>CompletionCallback</code>.
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Method>
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallback NewCallback(Method method) {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NewCallbackHelper(new Dispatcher0<Method>(method));
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// NewOptionalCallback() allocates a new, single-use
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// <code>CompletionCallback</code> that might not run if the method
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// taking it can complete synchronously. Thus, if after passing the
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// CompletionCallback to a Pepper method, the method does not return
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// PP_OK_COMPLETIONPENDING, then you should manually call the
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// CompletionCallback's Run method, or memory will be leaked.
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param[in] method The method to be invoked upon completion of the
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// operation.
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @return A <code>CompletionCallback</code>.
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Method>
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallback NewOptionalCallback(Method method) {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CompletionCallback cc = NewCallback(method);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return cc;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// NewCallbackWithOutput() allocates a new, single-use
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// <code>CompletionCallback</code> where the browser will pass an additional
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /// parameter containing the result of the request. The
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// <code>CompletionCallback</code> must be run in order for the memory
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// allocated by the methods to be freed.
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param[in] method The method to be invoked upon completion of the
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// operation.
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @return A <code>CompletionCallback</code>.
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Output>
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallbackWithOutput<
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      typename internal::TypeUnwrapper<Output>::StorageType>
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NewCallbackWithOutput(void (T::*method)(int32_t, Output)) {
2945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return NewCallbackWithOutputHelper(new DispatcherWithOutput0<
2955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        typename internal::TypeUnwrapper<Output>::StorageType,
2965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        void (T::*)(int32_t, Output)>(method));
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// NewCallback() allocates a new, single-use <code>CompletionCallback</code>.
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// The <code>CompletionCallback</code> must be run in order for the memory
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// allocated by the methods to be freed.
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param[in] method The method to be invoked upon completion of the
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// operation. Method should be of type:
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// <code>void (T::*)(int32_t result, const A& a)</code>
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param[in] a Passed to <code>method</code> when the completion callback
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// runs.
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @return A <code>CompletionCallback</code>.
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Method, typename A>
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallback NewCallback(Method method, const A& a) {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NewCallbackHelper(new Dispatcher1<Method, A>(method, a));
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// NewOptionalCallback() allocates a new, single-use
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// <code>CompletionCallback</code> that might not run if the method
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// taking it can complete synchronously. Thus, if after passing the
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// CompletionCallback to a Pepper method, the method does not return
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// PP_OK_COMPLETIONPENDING, then you should manually call the
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// CompletionCallback's Run method, or memory will be leaked.
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param[in] method The method to be invoked upon completion of the
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// operation. Method should be of type:
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// <code>void (T::*)(int32_t result, const A& a)</code>
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param[in] a Passed to <code>method</code> when the completion callback
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// runs.
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @return A <code>CompletionCallback</code>.
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Method, typename A>
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallback NewOptionalCallback(Method method, const A& a) {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CompletionCallback cc = NewCallback(method, a);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return cc;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// NewCallbackWithOutput() allocates a new, single-use
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// <code>CompletionCallback</code> where the browser will pass an additional
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /// parameter containing the result of the request. The
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// <code>CompletionCallback</code> must be run in order for the memory
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// allocated by the methods to be freed.
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param[in] method The method to be invoked upon completion of the
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// operation.
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param[in] a Passed to <code>method</code> when the completion callback
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// runs.
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @return A <code>CompletionCallback</code>.
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Output, typename A>
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallbackWithOutput<
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      typename internal::TypeUnwrapper<Output>::StorageType>
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NewCallbackWithOutput(void (T::*method)(int32_t, Output, A),
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const A& a) {
3565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return NewCallbackWithOutputHelper(new DispatcherWithOutput1<
3575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        typename internal::TypeUnwrapper<Output>::StorageType,
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        void (T::*)(int32_t, Output, A),
3595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        typename internal::TypeUnwrapper<A>::StorageType>(method, a));
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// NewCallback() allocates a new, single-use
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// <code>CompletionCallback</code>.
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// The <code>CompletionCallback</code> must be run in order for the memory
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// allocated by the methods to be freed.
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param method The method taking the callback. Method should be of type:
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code>
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param[in] a Passed to <code>method</code> when the completion callback
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// runs.
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param[in] b Passed to <code>method</code> when the completion callback
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// runs.
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @return A <code>CompletionCallback</code>.
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Method, typename A, typename B>
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallback NewCallback(Method method, const A& a, const B& b) {
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NewCallbackHelper(new Dispatcher2<Method, A, B>(method, a, b));
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// NewOptionalCallback() allocates a new, single-use
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// <code>CompletionCallback</code> that might not run if the method
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// taking it can complete synchronously. Thus, if after passing the
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// CompletionCallback to a Pepper method, the method does not return
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// PP_OK_COMPLETIONPENDING, then you should manually call the
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// CompletionCallback's Run method, or memory will be leaked.
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param[in] method The method taking the callback. Method should be of
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// type:
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code>
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param[in] a Passed to <code>method</code> when the completion callback
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// runs.
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param[in] b Passed to <code>method</code> when the completion callback
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// runs.
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @return A <code>CompletionCallback</code>.
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Method, typename A, typename B>
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallback NewOptionalCallback(Method method, const A& a,
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const B& b) {
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CompletionCallback cc = NewCallback(method, a, b);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return cc;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// NewCallbackWithOutput() allocates a new, single-use
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// <code>CompletionCallback</code> where the browser will pass an additional
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /// parameter containing the result of the request. The
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// <code>CompletionCallback</code> must be run in order for the memory
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// allocated by the methods to be freed.
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param[in] method The method to be invoked upon completion of the
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// operation.
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param[in] a Passed to <code>method</code> when the completion callback
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// runs.
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param[in] b Passed to <code>method</code> when the completion callback
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// runs.
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @return A <code>CompletionCallback</code>.
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Output, typename A, typename B>
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallbackWithOutput<
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      typename internal::TypeUnwrapper<Output>::StorageType>
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NewCallbackWithOutput(void (T::*method)(int32_t, Output, A, B),
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const A& a,
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const B& b) {
4305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return NewCallbackWithOutputHelper(new DispatcherWithOutput2<
4315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        typename internal::TypeUnwrapper<Output>::StorageType,
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        void (T::*)(int32_t, Output, A, B),
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        typename internal::TypeUnwrapper<A>::StorageType,
4345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        typename internal::TypeUnwrapper<B>::StorageType>(method, a, b));
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// NewCallback() allocates a new, single-use
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// <code>CompletionCallback</code>.
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// The <code>CompletionCallback</code> must be run in order for the memory
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// allocated by the methods to be freed.
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param method The method taking the callback. Method should be of type:
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// <code>
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// void (T::*)(int32_t result, const A& a, const B& b, const C& c)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// </code>
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param[in] a Passed to <code>method</code> when the completion callback
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// runs.
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param[in] b Passed to <code>method</code> when the completion callback
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// runs.
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param[in] c Passed to <code>method</code> when the completion callback
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// runs.
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @return A <code>CompletionCallback</code>.
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Method, typename A, typename B, typename C>
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallback NewCallback(Method method, const A& a, const B& b,
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const C& c) {
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NewCallbackHelper(new Dispatcher3<Method, A, B, C>(method, a, b, c));
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// NewOptionalCallback() allocates a new, single-use
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// <code>CompletionCallback</code> that might not run if the method
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// taking it can complete synchronously. Thus, if after passing the
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// CompletionCallback to a Pepper method, the method does not return
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// PP_OK_COMPLETIONPENDING, then you should manually call the
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// CompletionCallback's Run method, or memory will be leaked.
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param[in] method The method taking the callback. Method should be of
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// type:
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// <code>
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// void (T::*)(int32_t result, const A& a, const B& b, const C& c)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// </code>
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param[in] a Passed to <code>method</code> when the completion callback
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// runs.
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param[in] b Passed to <code>method</code> when the completion callback
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// runs.
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param[in] c Passed to <code>method</code> when the completion callback
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// runs.
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @return A <code>CompletionCallback</code>.
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Method, typename A, typename B, typename C>
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallback NewOptionalCallback(Method method, const A& a,
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const B& b, const C& c) {
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CompletionCallback cc = NewCallback(method, a, b, c);
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return cc;
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// NewCallbackWithOutput() allocates a new, single-use
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// <code>CompletionCallback</code> where the browser will pass an additional
496c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /// parameter containing the result of the request. The
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// <code>CompletionCallback</code> must be run in order for the memory
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// allocated by the methods to be freed.
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param method The method to be run.
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param[in] a Passed to <code>method</code> when the completion callback
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// runs.
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param[in] b Passed to <code>method</code> when the completion callback
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// runs.
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @param[in] c Passed to <code>method</code> when the completion callback
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// runs.
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ///
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /// @return A <code>CompletionCallback</code>.
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Output, typename A, typename B, typename C>
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallbackWithOutput<
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      typename internal::TypeUnwrapper<Output>::StorageType>
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NewCallbackWithOutput(void (T::*method)(int32_t, Output, A, B, C),
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const A& a,
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const B& b,
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const C& c) {
5195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return NewCallbackWithOutputHelper(new DispatcherWithOutput3<
5205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        typename internal::TypeUnwrapper<Output>::StorageType,
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        void (T::*)(int32_t, Output, A, B, C),
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        typename internal::TypeUnwrapper<A>::StorageType,
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        typename internal::TypeUnwrapper<B>::StorageType,
5245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        typename internal::TypeUnwrapper<C>::StorageType>(method, a, b, c));
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class BackPointer {
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typedef CompletionCallbackFactory<T, ThreadTraits> FactoryType;
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    explicit BackPointer(FactoryType* factory)
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : factory_(factory) {
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void AddRef() {
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ref_.AddRef();
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void Release() {
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (ref_.Release() == 0)
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delete this;
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void DropFactory() {
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      factory_ = NULL;
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    T* GetObject() {
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return factory_ ? factory_->GetObject() : NULL;
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typename ThreadTraits::RefCount ref_;
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FactoryType* factory_;
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Dispatcher>
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class CallbackData {
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Takes ownership of the given dispatcher pointer.
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CallbackData(BackPointer* back_pointer, Dispatcher* dispatcher)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : back_pointer_(back_pointer),
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          dispatcher_(dispatcher) {
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      back_pointer_->AddRef();
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ~CallbackData() {
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      back_pointer_->Release();
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete dispatcher_;
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Dispatcher* dispatcher() { return dispatcher_; }
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static void Thunk(void* user_data, int32_t result) {
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Self* self = static_cast<Self*>(user_data);
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      T* object = self->back_pointer_->GetObject();
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Please note that |object| may be NULL at this point. But we still need
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // to call into Dispatcher::operator() in that case, so that it can do
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // necessary cleanup.
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (*self->dispatcher_)(object, result);
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete self;
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typedef CallbackData<Dispatcher> Self;
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BackPointer* back_pointer_;  // We own a ref to this refcounted object.
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Dispatcher* dispatcher_;  // We own this pointer.
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Disallow copying & assignment.
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CallbackData(const CallbackData<Dispatcher>&);
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CallbackData<Dispatcher>& operator=(const CallbackData<Dispatcher>&);
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Method>
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class Dispatcher0 {
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Dispatcher0() : method_(NULL) {}
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    explicit Dispatcher0(Method method) : method_(method) {
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void operator()(T* object, int32_t result) {
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (object)
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (object->*method_)(result);
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Method method_;
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  template <typename Output, typename Method>
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class DispatcherWithOutput0 {
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typedef Output OutputType;
6155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    typedef internal::CallbackOutputTraits<Output> Traits;
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DispatcherWithOutput0()
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : method_(NULL),
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          output_() {
6207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      Traits::Initialize(&output_);
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DispatcherWithOutput0(Method method)
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : method_(method),
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          output_() {
6257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      Traits::Initialize(&output_);
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void operator()(T* object, int32_t result) {
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We must call Traits::StorageToPluginArg() even if we don't need to call
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the callback anymore, otherwise we may leak resource or var references.
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (object)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (object->*method_)(result, Traits::StorageToPluginArg(output_));
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Traits::StorageToPluginArg(output_);
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typename Traits::StorageType* output() {
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return &output_;
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Method method_;
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typename Traits::StorageType output_;
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Method, typename A>
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class Dispatcher1 {
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Dispatcher1()
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : method_(NULL),
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          a_() {
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Dispatcher1(Method method, const A& a)
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : method_(method),
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          a_(a) {
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void operator()(T* object, int32_t result) {
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (object)
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (object->*method_)(result, a_);
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Method method_;
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    A a_;
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  template <typename Output, typename Method, typename A>
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class DispatcherWithOutput1 {
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typedef Output OutputType;
6685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    typedef internal::CallbackOutputTraits<Output> Traits;
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DispatcherWithOutput1()
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : method_(NULL),
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          a_(),
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          output_() {
6747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      Traits::Initialize(&output_);
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DispatcherWithOutput1(Method method, const A& a)
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : method_(method),
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          a_(a),
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          output_() {
6807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      Traits::Initialize(&output_);
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void operator()(T* object, int32_t result) {
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We must call Traits::StorageToPluginArg() even if we don't need to call
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the callback anymore, otherwise we may leak resource or var references.
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (object)
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (object->*method_)(result, Traits::StorageToPluginArg(output_), a_);
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Traits::StorageToPluginArg(output_);
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typename Traits::StorageType* output() {
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return &output_;
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Method method_;
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    A a_;
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typename Traits::StorageType output_;
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Method, typename A, typename B>
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class Dispatcher2 {
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Dispatcher2()
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : method_(NULL),
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          a_(),
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          b_() {
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Dispatcher2(Method method, const A& a, const B& b)
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : method_(method),
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          a_(a),
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          b_(b) {
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void operator()(T* object, int32_t result) {
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (object)
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (object->*method_)(result, a_, b_);
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Method method_;
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    A a_;
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    B b_;
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  template <typename Output, typename Method, typename A, typename B>
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class DispatcherWithOutput2 {
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typedef Output OutputType;
7275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    typedef internal::CallbackOutputTraits<Output> Traits;
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DispatcherWithOutput2()
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : method_(NULL),
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          a_(),
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          b_(),
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          output_() {
7347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      Traits::Initialize(&output_);
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DispatcherWithOutput2(Method method, const A& a, const B& b)
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : method_(method),
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          a_(a),
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          b_(b),
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          output_() {
7417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      Traits::Initialize(&output_);
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void operator()(T* object, int32_t result) {
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We must call Traits::StorageToPluginArg() even if we don't need to call
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the callback anymore, otherwise we may leak resource or var references.
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (object)
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (object->*method_)(result, Traits::StorageToPluginArg(output_), a_, b_);
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Traits::StorageToPluginArg(output_);
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typename Traits::StorageType* output() {
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return &output_;
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Method method_;
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    A a_;
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    B b_;
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typename Traits::StorageType output_;
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Method, typename A, typename B, typename C>
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class Dispatcher3 {
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Dispatcher3()
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : method_(NULL),
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          a_(),
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          b_(),
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          c_() {
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Dispatcher3(Method method, const A& a, const B& b, const C& c)
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : method_(method),
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          a_(a),
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          b_(b),
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          c_(c) {
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void operator()(T* object, int32_t result) {
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (object)
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (object->*method_)(result, a_, b_, c_);
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Method method_;
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    A a_;
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    B b_;
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    C c_;
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  template <typename Output, typename Method, typename A, typename B,
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            typename C>
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class DispatcherWithOutput3 {
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typedef Output OutputType;
7935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    typedef internal::CallbackOutputTraits<Output> Traits;
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DispatcherWithOutput3()
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : method_(NULL),
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          a_(),
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          b_(),
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          c_(),
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          output_() {
8017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      Traits::Initialize(&output_);
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DispatcherWithOutput3(Method method, const A& a, const B& b, const C& c)
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : method_(method),
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          a_(a),
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          b_(b),
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          c_(c),
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          output_() {
8097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      Traits::Initialize(&output_);
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void operator()(T* object, int32_t result) {
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We must call Traits::StorageToPluginArg() even if we don't need to call
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the callback anymore, otherwise we may leak resource or var references.
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (object) {
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (object->*method_)(result, Traits::StorageToPluginArg(output_),
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           a_, b_, c_);
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Traits::StorageToPluginArg(output_);
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typename Traits::StorageType* output() {
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return &output_;
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Method method_;
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    A a_;
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    B b_;
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    C c_;
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typename Traits::StorageType output_;
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creates the back pointer object and takes a reference to it. This assumes
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // either that the lock is held or that it is not needed.
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void InitBackPointer() {
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    back_pointer_ = new BackPointer(this);
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    back_pointer_->AddRef();
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Releases our reference to the back pointer object and clears the pointer.
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This assumes either that the lock is held or that it is not needed.
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ResetBackPointer() {
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    back_pointer_->DropFactory();
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    back_pointer_->Release();
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    back_pointer_ = NULL;
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Takes ownership of the dispatcher pointer, which should be heap allocated.
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename Dispatcher>
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallback NewCallbackHelper(Dispatcher* dispatcher) {
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typename ThreadTraits::AutoLock lock(lock_);
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_DCHECK(object_);  // Expects a non-null object!
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return CompletionCallback(
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &CallbackData<Dispatcher>::Thunk,
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new CallbackData<Dispatcher>(back_pointer_, dispatcher));
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Takes ownership of the dispatcher pointer, which should be heap allocated.
8605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  template <typename Dispatcher> CompletionCallbackWithOutput<
8615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      typename internal::TypeUnwrapper<
8625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          typename Dispatcher::OutputType>::StorageType>
8635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  NewCallbackWithOutputHelper(Dispatcher* dispatcher) {
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typename ThreadTraits::AutoLock lock(lock_);
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_DCHECK(object_);  // Expects a non-null object!
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CallbackData<Dispatcher>* data =
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new CallbackData<Dispatcher>(back_pointer_, dispatcher);
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return CompletionCallbackWithOutput<typename Dispatcher::OutputType>(
8715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        &CallbackData<Dispatcher>::Thunk,
8725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        data,
8735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        data->dispatcher()->output());
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Disallowed:
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallbackFactory(const CompletionCallbackFactory&);
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallbackFactory& operator=(const CompletionCallbackFactory&);
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Never changed once initialized so does not need protection by the lock.
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  T* object_;
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Protects the back pointer.
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typename ThreadTraits::Lock lock_;
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Protected by the lock. This will get reset when you do CancelAll, for
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // example.
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BackPointer* back_pointer_;
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace pp
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_
894