| Index: ppapi/utility/completion_callback_factory.h
|
| diff --git a/ppapi/utility/completion_callback_factory.h b/ppapi/utility/completion_callback_factory.h
|
| index e0b1f37bdcc7dfbc1a9de0fdf03833eff9572df7..964cd0274836ea499c59dd291629c14d9e658757 100644
|
| --- a/ppapi/utility/completion_callback_factory.h
|
| +++ b/ppapi/utility/completion_callback_factory.h
|
| @@ -10,6 +10,27 @@
|
|
|
| namespace pp {
|
|
|
| +// TypeUnwrapper --------------------------------------------------------------
|
| +
|
| +namespace internal {
|
| +
|
| +// The TypeUnwrapper converts references and const references to the
|
| +// underlying type used for storage and passing as an argument. It is for
|
| +// internal use only.
|
| +template <typename T> struct TypeUnwrapper {
|
| + typedef T StorageType;
|
| +};
|
| +template <typename T> struct TypeUnwrapper<T&> {
|
| + typedef T StorageType;
|
| +};
|
| +template <typename T> struct TypeUnwrapper<const T&> {
|
| + typedef T StorageType;
|
| +};
|
| +
|
| +} // namespace internal
|
| +
|
| +// ----------------------------------------------------------------------------
|
| +
|
| /// CompletionCallbackFactory<T> may be used to create CompletionCallback
|
| /// objects that are bound to member functions.
|
| ///
|
| @@ -30,68 +51,137 @@ namespace pp {
|
| /// <strong>Example: </strong>
|
| ///
|
| /// @code
|
| -///
|
| -/// class MyHandler {
|
| +/// class MyClass {
|
| /// public:
|
| /// // If an compiler warns on following using |this| in the initializer
|
| /// // list, use PP_ALLOW_THIS_IN_INITIALIZER_LIST macro.
|
| -/// MyHandler() : factory_(this), offset_(0) {
|
| +/// MyClass() : factory_(this) {
|
| /// }
|
| ///
|
| -/// void ProcessFile(const FileRef& file) {
|
| -/// CompletionCallback cc = factory_.NewCallback(
|
| -/// &MyHandler::DidOpen);
|
| -/// int32_t rv = fio_.Open(file, PP_FileOpenFlag_Read, cc);
|
| +/// void OpenFile(const pp::FileRef& file) {
|
| +/// pp::CompletionCallback cc = factory_.NewCallback(&MyClass::DidOpen);
|
| +/// int32_t rv = file_io_.Open(file, PP_FileOpenFlag_Read, cc);
|
| /// CHECK(rv == PP_OK_COMPLETIONPENDING);
|
| /// }
|
| ///
|
| /// private:
|
| -/// CompletionCallback NewCallback() {
|
| -/// return factory_.NewCallback(&MyHandler::DidCompleteIO);
|
| -/// }
|
| -///
|
| /// void DidOpen(int32_t result) {
|
| /// if (result == PP_OK) {
|
| /// // The file is open, and we can begin reading.
|
| -/// offset_ = 0;
|
| -/// ReadMore();
|
| +/// // ...
|
| /// } else {
|
| /// // Failed to open the file with error given by 'result'.
|
| /// }
|
| /// }
|
| ///
|
| -/// void DidRead(int32_t result) {
|
| -/// if (result > 0) {
|
| -/// // buf_ now contains 'result' number of bytes from the file.
|
| -/// ProcessBytes(buf_, result);
|
| -/// offset_ += result;
|
| -/// ReadMore();
|
| -/// } else {
|
| -/// // Done reading (possibly with an error given by 'result').
|
| -/// }
|
| -/// }
|
| +/// pp::CompletionCallbackFactory<MyClass> factory_;
|
| +/// };
|
| +/// @endcode
|
| ///
|
| -/// void ReadMore() {
|
| -/// CompletionCallback cc =
|
| -/// factory_.NewOptionalCallback(&MyHandler::DidRead);
|
| -/// int32_t rv = fio_.Read(offset_, buf_, sizeof(buf_),
|
| -/// cc.pp_completion_callback());
|
| -/// if (rv != PP_OK_COMPLETIONPENDING)
|
| -/// cc.Run(rv);
|
| -/// }
|
| +/// <strong>Passing additional parameters to your callback</strong>
|
| ///
|
| -/// void ProcessBytes(const char* bytes, int32_t length) {
|
| -/// // Do work ...
|
| -/// }
|
| +/// As a convenience, the <code>CompletionCallbackFactory</code> can optionally
|
| +/// create a closure with up to three bound parameters that it will pass to
|
| +/// your callback function. This can be useful for passing information about
|
| +/// the request to your callback function, which is especially useful if your
|
| +/// class has multiple asynchronous callbacks pending.
|
| ///
|
| -/// pp::CompletionCallbackFactory<MyHandler> factory_;
|
| -/// pp::FileIO fio_;
|
| -/// char buf_[4096];
|
| -/// int64_t offset_;
|
| -/// };
|
| +/// For the above example, of opening a file, let's say you want to keep some
|
| +/// description associated with your request, you might implement your OpenFile
|
| +/// and DidOpen callback as follows:
|
| ///
|
| +/// @code
|
| +/// void OpenFile(const pp::FileRef& file) {
|
| +/// std::string message = "Opening file!";
|
| +/// pp::CompletionCallback cc = factory_.NewCallback(&MyClass::DidOpen,
|
| +/// message);
|
| +/// int32_t rv = file_io_.Open(file, PP_FileOpenFlag_Read, cc);
|
| +/// CHECK(rv == PP_OK_COMPLETIONPENDING);
|
| +/// }
|
| +/// void DidOpen(int32_t result, const std::string& message) {
|
| +/// // "message" will be "Opening file!".
|
| +/// ...
|
| +/// }
|
| +/// @endcode
|
| +///
|
| +/// <strong>Optional versus required callbacks</strong>
|
| +///
|
| +/// When you create an "optional" callback, the browser may return the results
|
| +/// synchronously if they are available. This can allow for higher performance
|
| +/// in some cases if data is available quickly (for example, for network loads
|
| +/// where there may be a lot of data coming quickly). In this case, the
|
| +/// callback will never be run.
|
| +///
|
| +/// When creating a new callback with the factory, there will be data allocated
|
| +/// on the heap that tracks the callback information and any bound arguments.
|
| +/// This data is freed when the callback executes. In the case of optional
|
| +/// callbacks, since the browser will never issue the callback, the internal
|
| +/// tracking data will be leaked.
|
| +///
|
| +/// Therefore, if you use optional callbacks, it's important to manually
|
| +/// issue the callback to free up this data. The typical pattern is:
|
| +///
|
| +/// @code
|
| +/// pp::CompletionCallback callback = callback_factory.NewOptionalCallback(
|
| +/// &MyClass::OnDataReady);
|
| +/// int32_t result = interface->GetData(callback);
|
| +/// if (result != PP_OK_COMPLETIONPENDING)
|
| +/// callback.Run(result);
|
| /// @endcode
|
| ///
|
| +/// Because of this additional complexity, it's generally recommended that
|
| +/// you not use optional callbacks except when performance is more important
|
| +/// (such as loading large resources from the network). In most other cases,
|
| +/// the performance difference will not be worth the additional complexity,
|
| +/// and most functions may never actually have the ability to complete
|
| +/// synchronously.
|
| +///
|
| +/// <strong>Completion callbacks with output</strong>
|
| +///
|
| +/// For some API calls, the browser returns data to the caller via an output
|
| +/// parameter. These can be difficult to manage since the output parameter
|
| +/// must remain valid for as long as the callback is pending. Note also that
|
| +/// CancelAll (or destroying the callback factory) does <i>not</i> cancel the
|
| +/// callback from the browser's perspective, only the execution of the callback
|
| +/// in the plugin code, and the output parameter will still be written to!
|
| +/// This means that you can't use class members as output parameters without
|
| +/// risking crashes.
|
| +///
|
| +/// To make this case easier, the CompletionCallbackFactory can allocate and
|
| +/// manage the output data for you and pass it to your callback function. This
|
| +/// makes such calls more natural and less error-prone.
|
| +///
|
| +/// To create such a callback, use NewCallbackWithOutput and specify a callback
|
| +/// function that takes the output parameter as its second argument. Let's say
|
| +/// you're calling a function GetFile which asynchronously returns a
|
| +/// pp::FileRef. GetFile's signature will be <code>int32_t GetFile(const
|
| +/// CompletionCallbackWithOutput<pp::FileRef>& callback);</code> and your
|
| +/// calling code would look like this:
|
| +///
|
| +/// @code
|
| +/// void RequestFile() {
|
| +/// file_interface->GetFile(callback_factory_.NewCallbackWithOutput(
|
| +/// &MyClass::GotFile));
|
| +/// }
|
| +/// void GotFile(int32_t result, const pp::FileRef& file) {
|
| +/// if (result == PP_OK) {
|
| +/// ...use file...
|
| +/// } else {
|
| +/// ...handle error...
|
| +/// }
|
| +/// }
|
| +/// @endcode
|
| +///
|
| +/// As with regular completion callbacks, you can optionally add up to three
|
| +/// bound arguments. These are passed following the output argument.
|
| +///
|
| +/// Your callback may take the output argument as a copy (common for small
|
| +/// types like integers, a const reference (common for structures and
|
| +/// resources to avoid an extra copy), or as a non-const reference. One
|
| +/// optimization you can do if your callback function may take large arrays
|
| +/// is to accept your output argument as a non-const reference and to swap()
|
| +/// the argument with a vector of your own to store it. This means you don't
|
| +/// have to copy the buffer to consume it.
|
| template <typename T, typename RefCount = NonThreadSafeRefCount>
|
| class CompletionCallbackFactory {
|
| public:
|
| @@ -155,7 +245,7 @@ class CompletionCallbackFactory {
|
| template <typename Method>
|
| CompletionCallback NewCallback(Method method) {
|
| PP_DCHECK(object_);
|
| - return NewCallbackHelper(Dispatcher0<Method>(method));
|
| + return NewCallbackHelper(new Dispatcher0<Method>(method));
|
| }
|
|
|
| /// NewOptionalCallback() allocates a new, single-use
|
| @@ -176,6 +266,25 @@ class CompletionCallbackFactory {
|
| return cc;
|
| }
|
|
|
| + /// NewCallbackWithOutput() allocates a new, single-use
|
| + /// <code>CompletionCallback</code> where the browser will pass an additional
|
| + /// parameter comtaining the result of the request. The
|
| + /// <code>CompletionCallback</code> must be run in order for the memory
|
| + /// allocated by the methods to be freed.
|
| + ///
|
| + /// @param[in] method The method to be invoked upon completion of the
|
| + /// operation.
|
| + ///
|
| + /// @return A <code>CompletionCallback</code>.
|
| + template <typename Output>
|
| + CompletionCallbackWithOutput<
|
| + typename internal::TypeUnwrapper<Output>::StorageType>
|
| + NewCallbackWithOutput(void (T::*method)(int32_t, Output)) {
|
| + return NewCallbackWithOutputHelper(new DispatcherWithOutput0<
|
| + typename internal::TypeUnwrapper<Output>::StorageType,
|
| + void (T::*)(int32_t, Output)>(method));
|
| + }
|
| +
|
| /// NewCallback() allocates a new, single-use <code>CompletionCallback</code>.
|
| /// The <code>CompletionCallback</code> must be run in order for the memory
|
| /// allocated by the methods to be freed.
|
| @@ -191,7 +300,7 @@ class CompletionCallbackFactory {
|
| template <typename Method, typename A>
|
| CompletionCallback NewCallback(Method method, const A& a) {
|
| PP_DCHECK(object_);
|
| - return NewCallbackHelper(Dispatcher1<Method, A>(method, a));
|
| + return NewCallbackHelper(new Dispatcher1<Method, A>(method, a));
|
| }
|
|
|
| /// NewOptionalCallback() allocates a new, single-use
|
| @@ -216,6 +325,30 @@ class CompletionCallbackFactory {
|
| return cc;
|
| }
|
|
|
| + /// NewCallbackWithOutput() allocates a new, single-use
|
| + /// <code>CompletionCallback</code> where the browser will pass an additional
|
| + /// parameter comtaining the result of the request. The
|
| + /// <code>CompletionCallback</code> must be run in order for the memory
|
| + /// allocated by the methods to be freed.
|
| + ///
|
| + /// @param[in] method The method to be invoked upon completion of the
|
| + /// operation.
|
| + ///
|
| + /// @param[in] a Passed to <code>method</code> when the completion callback
|
| + /// runs.
|
| + ///
|
| + /// @return A <code>CompletionCallback</code>.
|
| + template <typename Output, typename A>
|
| + CompletionCallbackWithOutput<
|
| + typename internal::TypeUnwrapper<Output>::StorageType>
|
| + NewCallbackWithOutput(void (T::*method)(int32_t, Output, A),
|
| + const A& a) {
|
| + return NewCallbackWithOutputHelper(new DispatcherWithOutput1<
|
| + typename internal::TypeUnwrapper<Output>::StorageType,
|
| + void (T::*)(int32_t, Output, A),
|
| + typename internal::TypeUnwrapper<A>::StorageType>(method, a));
|
| + }
|
| +
|
| /// NewCallback() allocates a new, single-use
|
| /// <code>CompletionCallback</code>.
|
| /// The <code>CompletionCallback</code> must be run in order for the memory
|
| @@ -234,7 +367,7 @@ class CompletionCallbackFactory {
|
| template <typename Method, typename A, typename B>
|
| CompletionCallback NewCallback(Method method, const A& a, const B& b) {
|
| PP_DCHECK(object_);
|
| - return NewCallbackHelper(Dispatcher2<Method, A, B>(method, a, b));
|
| + return NewCallbackHelper(new Dispatcher2<Method, A, B>(method, a, b));
|
| }
|
|
|
| /// NewOptionalCallback() allocates a new, single-use
|
| @@ -263,6 +396,35 @@ class CompletionCallbackFactory {
|
| return cc;
|
| }
|
|
|
| + /// NewCallbackWithOutput() allocates a new, single-use
|
| + /// <code>CompletionCallback</code> where the browser will pass an additional
|
| + /// parameter comtaining the result of the request. The
|
| + /// <code>CompletionCallback</code> must be run in order for the memory
|
| + /// allocated by the methods to be freed.
|
| + ///
|
| + /// @param[in] method The method to be invoked upon completion of the
|
| + /// operation.
|
| + ///
|
| + /// @param[in] a Passed to <code>method</code> when the completion callback
|
| + /// runs.
|
| + ///
|
| + /// @param[in] b Passed to <code>method</code> when the completion callback
|
| + /// runs.
|
| + ///
|
| + /// @return A <code>CompletionCallback</code>.
|
| + template <typename Output, typename A, typename B>
|
| + CompletionCallbackWithOutput<
|
| + typename internal::TypeUnwrapper<Output>::StorageType>
|
| + NewCallbackWithOutput(void (T::*method)(int32_t, Output, A, B),
|
| + const A& a,
|
| + const B& b) {
|
| + return NewCallbackWithOutputHelper(new DispatcherWithOutput2<
|
| + typename internal::TypeUnwrapper<Output>::StorageType,
|
| + void (T::*)(int32_t, Output, A, B),
|
| + typename internal::TypeUnwrapper<A>::StorageType,
|
| + typename internal::TypeUnwrapper<B>::StorageType>(method, a, b));
|
| + }
|
| +
|
| /// NewCallback() allocates a new, single-use
|
| /// <code>CompletionCallback</code>.
|
| /// The <code>CompletionCallback</code> must be run in order for the memory
|
| @@ -287,7 +449,7 @@ class CompletionCallbackFactory {
|
| CompletionCallback NewCallback(Method method, const A& a, const B& b,
|
| const C& c) {
|
| PP_DCHECK(object_);
|
| - return NewCallbackHelper(Dispatcher3<Method, A, B, C>(method, a, b, c));
|
| + return NewCallbackHelper(new Dispatcher3<Method, A, B, C>(method, a, b, c));
|
| }
|
|
|
| /// NewOptionalCallback() allocates a new, single-use
|
| @@ -321,12 +483,45 @@ class CompletionCallbackFactory {
|
| return cc;
|
| }
|
|
|
| + /// NewCallbackWithOutput() allocates a new, single-use
|
| + /// <code>CompletionCallback</code> where the browser will pass an additional
|
| + /// parameter comtaining the result of the request. The
|
| + /// <code>CompletionCallback</code> must be run in order for the memory
|
| + /// allocated by the methods to be freed.
|
| + ///
|
| + /// @param method The method to be run.
|
| + ///
|
| + /// @param[in] a Passed to <code>method</code> when the completion callback
|
| + /// runs.
|
| + ///
|
| + /// @param[in] b Passed to <code>method</code> when the completion callback
|
| + /// runs.
|
| + ///
|
| + /// @param[in] c Passed to <code>method</code> when the completion callback
|
| + /// runs.
|
| + ///
|
| + /// @return A <code>CompletionCallback</code>.
|
| + template <typename Output, typename A, typename B, typename C>
|
| + CompletionCallbackWithOutput<
|
| + typename internal::TypeUnwrapper<Output>::StorageType>
|
| + NewCallbackWithOutput(void (T::*method)(int32_t, Output, A, B, C),
|
| + const A& a,
|
| + const B& b,
|
| + const C& c) {
|
| + return NewCallbackWithOutputHelper(new DispatcherWithOutput3<
|
| + typename internal::TypeUnwrapper<Output>::StorageType,
|
| + void (T::*)(int32_t, Output, A, B, C),
|
| + typename internal::TypeUnwrapper<A>::StorageType,
|
| + typename internal::TypeUnwrapper<B>::StorageType,
|
| + typename internal::TypeUnwrapper<C>::StorageType>(method, a, b, c));
|
| + }
|
| +
|
| private:
|
| class BackPointer {
|
| public:
|
| typedef CompletionCallbackFactory<T, RefCount> FactoryType;
|
|
|
| - BackPointer(FactoryType* factory)
|
| + explicit BackPointer(FactoryType* factory)
|
| : factory_(factory) {
|
| }
|
|
|
| @@ -355,7 +550,8 @@ class CompletionCallbackFactory {
|
| template <typename Dispatcher>
|
| class CallbackData {
|
| public:
|
| - CallbackData(BackPointer* back_pointer, const Dispatcher& dispatcher)
|
| + // Takes ownership of the given dispatcher pointer.
|
| + CallbackData(BackPointer* back_pointer, Dispatcher* dispatcher)
|
| : back_pointer_(back_pointer),
|
| dispatcher_(dispatcher) {
|
| back_pointer_->AddRef();
|
| @@ -363,26 +559,34 @@ class CompletionCallbackFactory {
|
|
|
| ~CallbackData() {
|
| back_pointer_->Release();
|
| + delete dispatcher_;
|
| }
|
|
|
| + Dispatcher* dispatcher() { return dispatcher_; }
|
| +
|
| static void Thunk(void* user_data, int32_t result) {
|
| Self* self = static_cast<Self*>(user_data);
|
| T* object = self->back_pointer_->GetObject();
|
| if (object)
|
| - self->dispatcher_(object, result);
|
| + (*self->dispatcher_)(object, result);
|
| delete self;
|
| }
|
|
|
| private:
|
| typedef CallbackData<Dispatcher> Self;
|
| - BackPointer* back_pointer_;
|
| - Dispatcher dispatcher_;
|
| + BackPointer* back_pointer_; // We own a ref to this refcounted object.
|
| + Dispatcher* dispatcher_; // We own this pointer.
|
| +
|
| + // Disallow copying & assignment.
|
| + CallbackData(const CallbackData<Dispatcher>&);
|
| + CallbackData<Dispatcher>& operator=(const CallbackData<Dispatcher>&);
|
| };
|
|
|
| template <typename Method>
|
| class Dispatcher0 {
|
| public:
|
| - Dispatcher0(Method method) : method_(method) {
|
| + Dispatcher0() : method_(NULL) {}
|
| + explicit Dispatcher0(Method method) : method_(method) {
|
| }
|
| void operator()(T* object, int32_t result) {
|
| (object->*method_)(result);
|
| @@ -391,9 +595,31 @@ class CompletionCallbackFactory {
|
| Method method_;
|
| };
|
|
|
| + template <typename Output, typename Method>
|
| + class DispatcherWithOutput0 {
|
| + public:
|
| + typedef Output OutputType;
|
| + typedef internal::CallbackOutputTraits<Output> Traits;
|
| +
|
| + DispatcherWithOutput0() : method_(NULL) {}
|
| + DispatcherWithOutput0(Method method) : method_(method) {
|
| + }
|
| + void operator()(T* object, int32_t result) {
|
| + (object->*method_)(result, Traits::StorageToPluginArg(output_));
|
| + }
|
| + typename Traits::StorageType* output() {
|
| + return &output_;
|
| + }
|
| + private:
|
| + Method method_;
|
| +
|
| + typename Traits::StorageType output_;
|
| + };
|
| +
|
| template <typename Method, typename A>
|
| class Dispatcher1 {
|
| public:
|
| + Dispatcher1() : method_(NULL) {}
|
| Dispatcher1(Method method, const A& a)
|
| : method_(method),
|
| a_(a) {
|
| @@ -406,9 +632,34 @@ class CompletionCallbackFactory {
|
| A a_;
|
| };
|
|
|
| + template <typename Output, typename Method, typename A>
|
| + class DispatcherWithOutput1 {
|
| + public:
|
| + typedef Output OutputType;
|
| + typedef internal::CallbackOutputTraits<Output> Traits;
|
| +
|
| + DispatcherWithOutput1() : method_(NULL) {}
|
| + DispatcherWithOutput1(Method method, const A& a)
|
| + : method_(method),
|
| + a_(a) {
|
| + }
|
| + void operator()(T* object, int32_t result) {
|
| + (object->*method_)(result, Traits::StorageToPluginArg(output_), a_);
|
| + }
|
| + typename Traits::StorageType* output() {
|
| + return &output_;
|
| + }
|
| + private:
|
| + Method method_;
|
| + A a_;
|
| +
|
| + typename Traits::StorageType output_;
|
| + };
|
| +
|
| template <typename Method, typename A, typename B>
|
| class Dispatcher2 {
|
| public:
|
| + Dispatcher2() : method_(NULL) {}
|
| Dispatcher2(Method method, const A& a, const B& b)
|
| : method_(method),
|
| a_(a),
|
| @@ -423,9 +674,36 @@ class CompletionCallbackFactory {
|
| B b_;
|
| };
|
|
|
| + template <typename Output, typename Method, typename A, typename B>
|
| + class DispatcherWithOutput2 {
|
| + public:
|
| + typedef Output OutputType;
|
| + typedef internal::CallbackOutputTraits<Output> Traits;
|
| +
|
| + DispatcherWithOutput2() : method_(NULL) {}
|
| + DispatcherWithOutput2(Method method, const A& a, const B& b)
|
| + : method_(method),
|
| + a_(a),
|
| + b_(b) {
|
| + }
|
| + void operator()(T* object, int32_t result) {
|
| + (object->*method_)(result, Traits::StorageToPluginArg(output_), a_, b_);
|
| + }
|
| + typename Traits::StorageType* output() {
|
| + return &output_;
|
| + }
|
| + private:
|
| + Method method_;
|
| + A a_;
|
| + B b_;
|
| +
|
| + typename Traits::StorageType output_;
|
| + };
|
| +
|
| template <typename Method, typename A, typename B, typename C>
|
| class Dispatcher3 {
|
| public:
|
| + Dispatcher3() : method_(NULL) {}
|
| Dispatcher3(Method method, const A& a, const B& b, const C& c)
|
| : method_(method),
|
| a_(a),
|
| @@ -442,6 +720,36 @@ class CompletionCallbackFactory {
|
| C c_;
|
| };
|
|
|
| + template <typename Output, typename Method, typename A, typename B,
|
| + typename C>
|
| + class DispatcherWithOutput3 {
|
| + public:
|
| + typedef Output OutputType;
|
| + typedef internal::CallbackOutputTraits<Output> Traits;
|
| +
|
| + DispatcherWithOutput3() : method_(NULL) {}
|
| + DispatcherWithOutput3(Method method, const A& a, const B& b, const C& c)
|
| + : method_(method),
|
| + a_(a),
|
| + b_(b),
|
| + c_(c) {
|
| + }
|
| + void operator()(T* object, int32_t result) {
|
| + (object->*method_)(result, Traits::StorageToPluginArg(output_),
|
| + a_, b_, c_);
|
| + }
|
| + typename Traits::StorageType* output() {
|
| + return &output_;
|
| + }
|
| + private:
|
| + Method method_;
|
| + A a_;
|
| + B b_;
|
| + C c_;
|
| +
|
| + typename Traits::StorageType output_;
|
| + };
|
| +
|
| void InitBackPointer() {
|
| back_pointer_ = new BackPointer(this);
|
| back_pointer_->AddRef();
|
| @@ -452,14 +760,30 @@ class CompletionCallbackFactory {
|
| back_pointer_->Release();
|
| }
|
|
|
| + // Takes ownership of the dispatcher pointer, which should be heap allocated.
|
| template <typename Dispatcher>
|
| - CompletionCallback NewCallbackHelper(const Dispatcher& dispatcher) {
|
| + CompletionCallback NewCallbackHelper(Dispatcher* dispatcher) {
|
| PP_DCHECK(object_); // Expects a non-null object!
|
| return CompletionCallback(
|
| &CallbackData<Dispatcher>::Thunk,
|
| new CallbackData<Dispatcher>(back_pointer_, dispatcher));
|
| }
|
|
|
| + // Takes ownership of the dispatcher pointer, which should be heap allocated.
|
| + template <typename Dispatcher> CompletionCallbackWithOutput<
|
| + typename internal::TypeUnwrapper<
|
| + typename Dispatcher::OutputType>::StorageType>
|
| + NewCallbackWithOutputHelper(Dispatcher* dispatcher) {
|
| + PP_DCHECK(object_); // Expects a non-null object!
|
| + CallbackData<Dispatcher>* data =
|
| + new CallbackData<Dispatcher>(back_pointer_, dispatcher);
|
| +
|
| + return CompletionCallbackWithOutput<typename Dispatcher::OutputType>(
|
| + &CallbackData<Dispatcher>::Thunk,
|
| + data,
|
| + data->dispatcher()->output());
|
| + }
|
| +
|
| // Disallowed:
|
| CompletionCallbackFactory(const CompletionCallbackFactory&);
|
| CompletionCallbackFactory& operator=(const CompletionCallbackFactory&);
|
|
|