| Index: ppapi/utility/completion_callback_factory.h
|
| diff --git a/ppapi/cpp/completion_callback.h b/ppapi/utility/completion_callback_factory.h
|
| similarity index 74%
|
| copy from ppapi/cpp/completion_callback.h
|
| copy to ppapi/utility/completion_callback_factory.h
|
| index 2e5f38b9e9c11df90065c744f4ffe86edf03cfbb..b656024097c77ff338cbace98cc2703cd38ee4fe 100644
|
| --- a/ppapi/cpp/completion_callback.h
|
| +++ b/ppapi/utility/completion_callback_factory.h
|
| @@ -1,710 +1,564 @@
|
| -// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#ifndef PPAPI_CPP_COMPLETION_CALLBACK_H_
|
| -#define PPAPI_CPP_COMPLETION_CALLBACK_H_
|
| -
|
| -#include "ppapi/c/pp_completion_callback.h"
|
| -#include "ppapi/c/pp_errors.h"
|
| -#include "ppapi/cpp/logging.h"
|
| -#include "ppapi/cpp/non_thread_safe_ref_count.h"
|
| -
|
| -/// @file
|
| -/// This file defines the API to create and run a callback.
|
| -namespace pp {
|
| -
|
| -/// This API enables you to implement and receive callbacks when
|
| -/// Pepper operations complete asynchronously.
|
| -class CompletionCallback {
|
| - public:
|
| - /// The default constructor will create a blocking
|
| - /// <code>CompletionCallback</code> that can be passed to a method to
|
| - /// indicate that the calling thread should be blocked until the asynchronous
|
| - /// operation corresponding to the method completes.
|
| - ///
|
| - /// <strong>Note:</strong> Blocking completion callbacks are only allowed from
|
| - /// from background threads.
|
| - CompletionCallback() {
|
| - cc_ = PP_BlockUntilComplete();
|
| - }
|
| -
|
| - /// A constructor for creating a <code>CompletionCallback</code>.
|
| - ///
|
| - /// @param[in] func The function to be called on completion.
|
| - /// @param[in] user_data The user data to be passed to the callback function.
|
| - /// This is optional and is typically used to help track state in case of
|
| - /// multiple pending callbacks.
|
| - CompletionCallback(PP_CompletionCallback_Func func, void* user_data) {
|
| - cc_ = PP_MakeCompletionCallback(func, user_data);
|
| - }
|
| -
|
| - /// A constructor for creating a <code>CompletionCallback</code> with
|
| - /// specified flags.
|
| - ///
|
| - /// @param[in] func The function to be called on completion.
|
| - /// @param[in] user_data The user data to be passed to the callback function.
|
| - /// This is optional and is typically used to help track state in case of
|
| - /// multiple pending callbacks.
|
| - /// @param[in] flags Bit field combination of
|
| - /// <code>PP_CompletionCallback_Flag</code> flags used to control how
|
| - /// non-NULL callbacks are scheduled by asynchronous methods.
|
| - CompletionCallback(PP_CompletionCallback_Func func, void* user_data,
|
| - int32_t flags) {
|
| - cc_ = PP_MakeCompletionCallback(func, user_data);
|
| - cc_.flags = flags;
|
| - }
|
| -
|
| - /// The set_flags() function is used to set the flags used to control
|
| - /// how non-NULL callbacks are scheduled by asynchronous methods.
|
| - ///
|
| - /// @param[in] flags Bit field combination of
|
| - /// <code>PP_CompletionCallback_Flag</code> flags used to control how
|
| - /// non-NULL callbacks are scheduled by asynchronous methods.
|
| - void set_flags(int32_t flags) { cc_.flags = flags; }
|
| -
|
| - /// Run() is used to run the <code>CompletionCallback</code>.
|
| - /// Normally, the system runs a <code>CompletionCallback</code> after an
|
| - /// asynchronous operation completes, but programs may wish to run the
|
| - /// <code>CompletionCallback</code> manually in order to reuse the same code
|
| - /// paths.
|
| - ///
|
| - /// @param[in] result The result of the operation to be passed to the
|
| - /// callback function. Non-positive values correspond to the error codes
|
| - /// from <code>pp_errors.h</code> (excluding
|
| - /// <code>PP_OK_COMPLETIONPENDING</code>). Positive values indicate
|
| - /// additional information such as bytes read.
|
| - void Run(int32_t result) {
|
| - PP_DCHECK(cc_.func);
|
| - PP_RunCompletionCallback(&cc_, result);
|
| - }
|
| -
|
| - /// IsOptional() is used to determine the setting of the
|
| - /// <code>PP_COMPLETIONCALLBACK_FLAG_OPTIONAL</code> flag. This flag allows
|
| - /// any method taking such callback to complete synchronously
|
| - /// and not call the callback if the operation would not block. This is useful
|
| - /// when performance is an issue, and the operation bandwidth should not be
|
| - /// limited to the processing speed of the message loop.
|
| - ///
|
| - /// On synchronous method completion, the completion result will be returned
|
| - /// by the method itself. Otherwise, the method will return
|
| - /// PP_OK_COMPLETIONPENDING, and the callback will be invoked asynchronously
|
| - /// on the main thread of Pepper execution.
|
| - ///
|
| - /// @return true if this callback is optional, otherwise false.
|
| - bool IsOptional() const {
|
| - return (cc_.func == NULL ||
|
| - (cc_.flags & PP_COMPLETIONCALLBACK_FLAG_OPTIONAL) != 0);
|
| - }
|
| -
|
| - /// The pp_completion_callback() function returns the underlying
|
| - /// <code>PP_CompletionCallback</code>
|
| - ///
|
| - /// @return A <code>PP_CompletionCallback</code>.
|
| - const PP_CompletionCallback& pp_completion_callback() const { return cc_; }
|
| -
|
| - /// The flags() function returns flags used to control how non-NULL callbacks
|
| - /// are scheduled by asynchronous methods.
|
| - ///
|
| - /// @return An int32_t containing a bit field combination of
|
| - /// <code>PP_CompletionCallback_Flag</code> flags.
|
| - int32_t flags() const { return cc_.flags; }
|
| -
|
| - /// MayForce() is used when implementing functions taking callbacks.
|
| - /// If the callback is required and <code>result</code> indicates that it has
|
| - /// not been scheduled, it will be forced on the main thread.
|
| - ///
|
| - /// <strong>Example:</strong>
|
| - ///
|
| - /// @code
|
| - ///
|
| - /// int32_t OpenURL(pp::URLLoader* loader,
|
| - /// pp::URLRequestInfo* url_request_info,
|
| - /// const CompletionCallback& cc) {
|
| - /// if (loader == NULL || url_request_info == NULL)
|
| - /// return cc.MayForce(PP_ERROR_BADRESOURCE);
|
| - /// return loader->Open(*loader, *url_request_info, cc);
|
| - /// }
|
| - ///
|
| - /// @endcode
|
| - ///
|
| - /// @param[in] result PP_OK_COMPLETIONPENDING or the result of the completed
|
| - /// operation to be passed to the callback function. PP_OK_COMPLETIONPENDING
|
| - /// indicates that the callback has already been scheduled. Other
|
| - /// non-positive values correspond to error codes from
|
| - /// <code>pp_errors.h</code>. Positive values indicate additional information
|
| - /// such as bytes read.
|
| - ///
|
| - /// @return <code>PP_OK_COMPLETIONPENDING</code> if the callback has been
|
| - /// forced, result parameter otherwise.
|
| - int32_t MayForce(int32_t result) const {
|
| - if (result == PP_OK_COMPLETIONPENDING || IsOptional())
|
| - return result;
|
| - Module::Get()->core()->CallOnMainThread(0, *this, result);
|
| - return PP_OK_COMPLETIONPENDING;
|
| - }
|
| -
|
| - protected:
|
| - PP_CompletionCallback cc_;
|
| -};
|
| -
|
| -/// BlockUntilComplete() is used in place of an actual completion callback
|
| -/// to request blocking behavior. If specified, the calling thread will block
|
| -/// until the function completes. Blocking completion callbacks are only
|
| -/// allowed from background threads.
|
| -///
|
| -/// @return A <code>CompletionCallback</code> corresponding to a NULL callback.
|
| -CompletionCallback BlockUntilComplete();
|
| -
|
| -/// CompletionCallbackFactory<T> may be used to create CompletionCallback
|
| -/// objects that are bound to member functions.
|
| -///
|
| -/// If a factory is destroyed, then any pending callbacks will be cancelled
|
| -/// preventing any bound member functions from being called. The CancelAll()
|
| -/// method allows pending callbacks to be cancelled without destroying the
|
| -/// factory.
|
| -///
|
| -/// <strong>Note: </strong><code>CompletionCallbackFactory<T></code> isn't
|
| -/// thread safe, but you can make it more thread-friendly by passing a
|
| -/// thread-safe refcounting class as the second template element. However, it
|
| -/// only guarantees safety for creating a callback from another thread, the
|
| -/// callback itself needs to execute on the same thread as the thread that
|
| -/// creates/destroys the factory. With this restriction, it is safe to create
|
| -/// the <code>CompletionCallbackFactory</code> on the main thread, create
|
| -/// callbacks from any thread and pass them to CallOnMainThread().
|
| -///
|
| -/// <strong>Example: </strong>
|
| -///
|
| -/// @code
|
| -///
|
| -/// class MyHandler {
|
| -/// 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) {
|
| -/// }
|
| -///
|
| -/// void ProcessFile(const FileRef& file) {
|
| -/// CompletionCallback cc = factory_.NewRequiredCallback(
|
| -/// &MyHandler::DidOpen);
|
| -/// int32_t rv = fio_.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').
|
| -/// }
|
| -/// }
|
| -///
|
| -/// 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);
|
| -/// }
|
| -///
|
| -/// void ProcessBytes(const char* bytes, int32_t length) {
|
| -/// // Do work ...
|
| -/// }
|
| -///
|
| -/// pp::CompletionCallbackFactory<MyHandler> factory_;
|
| -/// pp::FileIO fio_;
|
| -/// char buf_[4096];
|
| -/// int64_t offset_;
|
| -/// };
|
| -///
|
| -/// @endcode
|
| -///
|
| -template <typename T, typename RefCount = NonThreadSafeRefCount>
|
| -class CompletionCallbackFactory {
|
| - public:
|
| -
|
| - /// This constructor creates a <code>CompletionCallbackFactory</code>
|
| - /// bound to an object. If the constructor is called without an argument,
|
| - /// the default value of <code>NULL</code> is used. The user then must call
|
| - /// Initialize() to initialize the object.
|
| - ///
|
| - /// param[in] object Optional parameter. An object whose member functions
|
| - /// are to be bound to CompletionCallbacks created by this
|
| - /// <code>CompletionCallbackFactory</code>. The default value of this
|
| - /// parameter is <code>NULL</code>.
|
| - explicit CompletionCallbackFactory(T* object = NULL)
|
| - : object_(object) {
|
| - InitBackPointer();
|
| - }
|
| -
|
| - /// Destructor.
|
| - ~CompletionCallbackFactory() {
|
| - ResetBackPointer();
|
| - }
|
| -
|
| - /// CancelAll() cancels all <code>CompletionCallbacks</code> allocated from
|
| - /// this factory.
|
| - void CancelAll() {
|
| - ResetBackPointer();
|
| - InitBackPointer();
|
| - }
|
| - /// Initialize() binds the <code>CallbackFactory</code> to a particular
|
| - /// object. Use this when the object is not available at
|
| - /// <code>CallbackFactory</code> creation, and the <code>NULL</code> default
|
| - /// is passed to the constructor. The object may only be initialized once,
|
| - /// either by the constructor, or by a call to Initialize().
|
| - ///
|
| - /// @param[in] object The object whose member functions are to be bound to
|
| - /// the <code>CompletionCallback</code> created by this
|
| - /// <code>CompletionCallbackFactory</code>.
|
| - void Initialize(T* object) {
|
| - PP_DCHECK(object);
|
| - PP_DCHECK(!object_); // May only initialize once!
|
| - object_ = object;
|
| - }
|
| -
|
| - /// GetObject() returns the object that was passed at initialization to
|
| - /// Intialize().
|
| - ///
|
| - /// @return the object passed to the constructor or Intialize().
|
| - T* GetObject() {
|
| - return object_;
|
| - }
|
| -
|
| - /// 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.
|
| - /// NewCallback() is equivalent to NewRequiredCallback() below.
|
| - ///
|
| - /// @param[in] method The method to be invoked upon completion of the
|
| - /// operation.
|
| - ///
|
| - /// @return A <code>CompletionCallback</code>.
|
| - template <typename Method>
|
| - CompletionCallback NewCallback(Method method) {
|
| - PP_DCHECK(object_);
|
| - return NewCallbackHelper(Dispatcher0<Method>(method));
|
| - }
|
| -
|
| - /// NewRequiredCallback() allocates a new, single-use
|
| - /// <code>CompletionCallback</code> that will always run. 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 Method>
|
| - CompletionCallback NewRequiredCallback(Method method) {
|
| - CompletionCallback cc = NewCallback(method);
|
| - cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
|
| - return cc;
|
| - }
|
| -
|
| - /// NewOptionalCallback() allocates a new, single-use
|
| - /// <code>CompletionCallback</code> that might not run if the method
|
| - /// taking it can complete synchronously. Thus, if after passing the
|
| - /// CompletionCallback to a Pepper method, the method does not return
|
| - /// PP_OK_COMPLETIONPENDING, then you should manually call the
|
| - /// CompletionCallback's Run method, or memory will be leaked.
|
| - ///
|
| - /// @param[in] method The method to be invoked upon completion of the
|
| - /// operation.
|
| - ///
|
| - /// @return A <code>CompletionCallback</code>.
|
| - template <typename Method>
|
| - CompletionCallback NewOptionalCallback(Method method) {
|
| - CompletionCallback cc = NewCallback(method);
|
| - cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
|
| - return cc;
|
| - }
|
| -
|
| - /// 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.
|
| - /// NewCallback() is equivalent to NewRequiredCallback() below.
|
| - ///
|
| - /// @param[in] method The method to be invoked upon completion of the
|
| - /// operation. Method should be of type:
|
| - /// <code>void (T::*)(int32_t result, const A& a)</code>
|
| - ///
|
| - /// @param[in] a Passed to <code>method</code> when the completion callback
|
| - /// runs.
|
| - ///
|
| - /// @return A <code>CompletionCallback</code>.
|
| - template <typename Method, typename A>
|
| - CompletionCallback NewCallback(Method method, const A& a) {
|
| - PP_DCHECK(object_);
|
| - return NewCallbackHelper(Dispatcher1<Method, A>(method, a));
|
| - }
|
| -
|
| - /// NewRequiredCallback() allocates a new, single-use
|
| - /// <code>CompletionCallback</code> that will always run. 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. Method should be of type:
|
| - /// <code>void (T::*)(int32_t result, const A& a)</code>
|
| - ///
|
| - /// @param[in] a Passed to <code>method</code> when the completion callback
|
| - /// runs.
|
| - ///
|
| - /// @return A <code>CompletionCallback</code>.
|
| - template <typename Method, typename A>
|
| - CompletionCallback NewRequiredCallback(Method method, const A& a) {
|
| - CompletionCallback cc = NewCallback(method, a);
|
| - cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
|
| - return cc;
|
| - }
|
| -
|
| - /// NewOptionalCallback() allocates a new, single-use
|
| - /// <code>CompletionCallback</code> that might not run if the method
|
| - /// taking it can complete synchronously. Thus, if after passing the
|
| - /// CompletionCallback to a Pepper method, the method does not return
|
| - /// PP_OK_COMPLETIONPENDING, then you should manually call the
|
| - /// CompletionCallback's Run method, or memory will be leaked.
|
| - ///
|
| - /// @param[in] method The method to be invoked upon completion of the
|
| - /// operation. Method should be of type:
|
| - /// <code>void (T::*)(int32_t result, const A& a)</code>
|
| - ///
|
| - /// @param[in] a Passed to <code>method</code> when the completion callback
|
| - /// runs.
|
| - ///
|
| - /// @return A <code>CompletionCallback</code>.
|
| - template <typename Method, typename A>
|
| - CompletionCallback NewOptionalCallback(Method method, const A& a) {
|
| - CompletionCallback cc = NewCallback(method, a);
|
| - cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
|
| - return cc;
|
| - }
|
| -
|
| - /// 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.
|
| - /// NewCallback() is equivalent to NewRequiredCallback() below.
|
| - ///
|
| - /// @param method The method taking the callback. Method should be of type:
|
| - /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code>
|
| - ///
|
| - /// @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 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));
|
| - }
|
| -
|
| - /// NewRequiredCallback() allocates a new, single-use
|
| - /// <code>CompletionCallback</code> that will always run. The
|
| - /// <code>CompletionCallback</code> must be run in order for the memory
|
| - /// allocated by the methods to be freed.
|
| - ///
|
| - /// @param method The method taking the callback. Method should be of type:
|
| - /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code>
|
| - ///
|
| - /// @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 Method, typename A, typename B>
|
| - CompletionCallback NewRequiredCallback(Method method, const A& a,
|
| - const B& b) {
|
| - CompletionCallback cc = NewCallback(method, a, b);
|
| - cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
|
| - return cc;
|
| - }
|
| -
|
| - /// NewOptionalCallback() allocates a new, single-use
|
| - /// <code>CompletionCallback</code> that might not run if the method
|
| - /// taking it can complete synchronously. Thus, if after passing the
|
| - /// CompletionCallback to a Pepper method, the method does not return
|
| - /// PP_OK_COMPLETIONPENDING, then you should manually call the
|
| - /// CompletionCallback's Run method, or memory will be leaked.
|
| - ///
|
| - /// @param[in] method The method taking the callback. Method should be of
|
| - /// type:
|
| - /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code>
|
| - ///
|
| - /// @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 Method, typename A, typename B>
|
| - CompletionCallback NewOptionalCallback(Method method, const A& a,
|
| - const B& b) {
|
| - CompletionCallback cc = NewCallback(method, a, b);
|
| - cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
|
| - return cc;
|
| - }
|
| -
|
| - /// 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.
|
| - /// NewCallback() is equivalent to NewRequiredCallback() below.
|
| - ///
|
| - /// @param method The method taking the callback. Method should be of type:
|
| - /// <code>
|
| - /// void (T::*)(int32_t result, const A& a, const B& b, const C& c)
|
| - /// </code>
|
| - ///
|
| - /// @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 Method, typename A, typename B, typename C>
|
| - 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));
|
| - }
|
| -
|
| - /// NewRequiredCallback() allocates a new, single-use
|
| - /// <code>CompletionCallback</code> that will always run. The
|
| - /// <code>CompletionCallback</code> must be run in order for the memory
|
| - /// allocated by the methods to be freed.
|
| - ///
|
| - /// @param method The method taking the callback. Method should be of type:
|
| - /// <code>
|
| - /// void (T::*)(int32_t result, const A& a, const B& b, const C& c)
|
| - /// </code>
|
| - ///
|
| - /// @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 Method, typename A, typename B, typename C>
|
| - CompletionCallback NewRequiredCallback(Method method, const A& a,
|
| - const B& b, const C& c) {
|
| - CompletionCallback cc = NewCallback(method, a, b, c);
|
| - cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
|
| - return cc;
|
| - }
|
| -
|
| - /// NewOptionalCallback() allocates a new, single-use
|
| - /// <code>CompletionCallback</code> that might not run if the method
|
| - /// taking it can complete synchronously. Thus, if after passing the
|
| - /// CompletionCallback to a Pepper method, the method does not return
|
| - /// PP_OK_COMPLETIONPENDING, then you should manually call the
|
| - /// CompletionCallback's Run method, or memory will be leaked.
|
| - ///
|
| - /// @param[in] method The method taking the callback. Method should be of
|
| - /// type:
|
| - /// <code>
|
| - /// void (T::*)(int32_t result, const A& a, const B& b, const C& c)
|
| - /// </code>
|
| - ///
|
| - /// @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 Method, typename A, typename B, typename C>
|
| - CompletionCallback NewOptionalCallback(Method method, const A& a,
|
| - const B& b, const C& c) {
|
| - CompletionCallback cc = NewCallback(method, a, b, c);
|
| - cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
|
| - return cc;
|
| - }
|
| -
|
| - private:
|
| - class BackPointer {
|
| - public:
|
| - typedef CompletionCallbackFactory<T, RefCount> FactoryType;
|
| -
|
| - BackPointer(FactoryType* factory)
|
| - : factory_(factory) {
|
| - }
|
| -
|
| - void AddRef() {
|
| - ref_.AddRef();
|
| - }
|
| -
|
| - void Release() {
|
| - if (ref_.Release() == 0)
|
| - delete this;
|
| - }
|
| -
|
| - void DropFactory() {
|
| - factory_ = NULL;
|
| - }
|
| -
|
| - T* GetObject() {
|
| - return factory_ ? factory_->GetObject() : NULL;
|
| - }
|
| -
|
| - private:
|
| - RefCount ref_;
|
| - FactoryType* factory_;
|
| - };
|
| -
|
| - template <typename Dispatcher>
|
| - class CallbackData {
|
| - public:
|
| - CallbackData(BackPointer* back_pointer, const Dispatcher& dispatcher)
|
| - : back_pointer_(back_pointer),
|
| - dispatcher_(dispatcher) {
|
| - back_pointer_->AddRef();
|
| - }
|
| -
|
| - ~CallbackData() {
|
| - back_pointer_->Release();
|
| - }
|
| -
|
| - 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);
|
| - delete self;
|
| - }
|
| -
|
| - private:
|
| - typedef CallbackData<Dispatcher> Self;
|
| - BackPointer* back_pointer_;
|
| - Dispatcher dispatcher_;
|
| - };
|
| -
|
| - template <typename Method>
|
| - class Dispatcher0 {
|
| - public:
|
| - Dispatcher0(Method method) : method_(method) {
|
| - }
|
| - void operator()(T* object, int32_t result) {
|
| - (object->*method_)(result);
|
| - }
|
| - private:
|
| - Method method_;
|
| - };
|
| -
|
| - template <typename Method, typename A>
|
| - class Dispatcher1 {
|
| - public:
|
| - Dispatcher1(Method method, const A& a)
|
| - : method_(method),
|
| - a_(a) {
|
| - }
|
| - void operator()(T* object, int32_t result) {
|
| - (object->*method_)(result, a_);
|
| - }
|
| - private:
|
| - Method method_;
|
| - A a_;
|
| - };
|
| -
|
| - template <typename Method, typename A, typename B>
|
| - class Dispatcher2 {
|
| - public:
|
| - Dispatcher2(Method method, const A& a, const B& b)
|
| - : method_(method),
|
| - a_(a),
|
| - b_(b) {
|
| - }
|
| - void operator()(T* object, int32_t result) {
|
| - (object->*method_)(result, a_, b_);
|
| - }
|
| - private:
|
| - Method method_;
|
| - A a_;
|
| - B b_;
|
| - };
|
| -
|
| - template <typename Method, typename A, typename B, typename C>
|
| - class Dispatcher3 {
|
| - public:
|
| - Dispatcher3(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, a_, b_, c_);
|
| - }
|
| - private:
|
| - Method method_;
|
| - A a_;
|
| - B b_;
|
| - C c_;
|
| - };
|
| -
|
| - void InitBackPointer() {
|
| - back_pointer_ = new BackPointer(this);
|
| - back_pointer_->AddRef();
|
| - }
|
| -
|
| - void ResetBackPointer() {
|
| - back_pointer_->DropFactory();
|
| - back_pointer_->Release();
|
| - }
|
| -
|
| - template <typename Dispatcher>
|
| - CompletionCallback NewCallbackHelper(const Dispatcher& dispatcher) {
|
| - PP_DCHECK(object_); // Expects a non-null object!
|
| - return CompletionCallback(
|
| - &CallbackData<Dispatcher>::Thunk,
|
| - new CallbackData<Dispatcher>(back_pointer_, dispatcher));
|
| - }
|
| -
|
| - // Disallowed:
|
| - CompletionCallbackFactory(const CompletionCallbackFactory&);
|
| - CompletionCallbackFactory& operator=(const CompletionCallbackFactory&);
|
| -
|
| - T* object_;
|
| - BackPointer* back_pointer_;
|
| -};
|
| -
|
| -} // namespace pp
|
| -
|
| -#endif // PPAPI_CPP_COMPLETION_CALLBACK_H_
|
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#ifndef PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_
|
| +#define PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_
|
| +
|
| +#include "ppapi/cpp/completion_callback.h"
|
| +#include "ppapi/utility/non_thread_safe_ref_count.h"
|
| +
|
| +namespace pp {
|
| +
|
| +/// CompletionCallbackFactory<T> may be used to create CompletionCallback
|
| +/// objects that are bound to member functions.
|
| +///
|
| +/// If a factory is destroyed, then any pending callbacks will be cancelled
|
| +/// preventing any bound member functions from being called. The CancelAll()
|
| +/// method allows pending callbacks to be cancelled without destroying the
|
| +/// factory.
|
| +///
|
| +/// <strong>Note: </strong><code>CompletionCallbackFactory<T></code> isn't
|
| +/// thread safe, but you can make it more thread-friendly by passing a
|
| +/// thread-safe refcounting class as the second template element. However, it
|
| +/// only guarantees safety for creating a callback from another thread, the
|
| +/// callback itself needs to execute on the same thread as the thread that
|
| +/// creates/destroys the factory. With this restriction, it is safe to create
|
| +/// the <code>CompletionCallbackFactory</code> on the main thread, create
|
| +/// callbacks from any thread and pass them to CallOnMainThread().
|
| +///
|
| +/// <strong>Example: </strong>
|
| +///
|
| +/// @code
|
| +///
|
| +/// class MyHandler {
|
| +/// 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) {
|
| +/// }
|
| +///
|
| +/// void ProcessFile(const FileRef& file) {
|
| +/// CompletionCallback cc = factory_.NewRequiredCallback(
|
| +/// &MyHandler::DidOpen);
|
| +/// int32_t rv = fio_.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').
|
| +/// }
|
| +/// }
|
| +///
|
| +/// 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);
|
| +/// }
|
| +///
|
| +/// void ProcessBytes(const char* bytes, int32_t length) {
|
| +/// // Do work ...
|
| +/// }
|
| +///
|
| +/// pp::CompletionCallbackFactory<MyHandler> factory_;
|
| +/// pp::FileIO fio_;
|
| +/// char buf_[4096];
|
| +/// int64_t offset_;
|
| +/// };
|
| +///
|
| +/// @endcode
|
| +///
|
| +template <typename T, typename RefCount = NonThreadSafeRefCount>
|
| +class CompletionCallbackFactory {
|
| + public:
|
| +
|
| + /// This constructor creates a <code>CompletionCallbackFactory</code>
|
| + /// bound to an object. If the constructor is called without an argument,
|
| + /// the default value of <code>NULL</code> is used. The user then must call
|
| + /// Initialize() to initialize the object.
|
| + ///
|
| + /// param[in] object Optional parameter. An object whose member functions
|
| + /// are to be bound to CompletionCallbacks created by this
|
| + /// <code>CompletionCallbackFactory</code>. The default value of this
|
| + /// parameter is <code>NULL</code>.
|
| + explicit CompletionCallbackFactory(T* object = NULL)
|
| + : object_(object) {
|
| + InitBackPointer();
|
| + }
|
| +
|
| + /// Destructor.
|
| + ~CompletionCallbackFactory() {
|
| + ResetBackPointer();
|
| + }
|
| +
|
| + /// CancelAll() cancels all <code>CompletionCallbacks</code> allocated from
|
| + /// this factory.
|
| + void CancelAll() {
|
| + ResetBackPointer();
|
| + InitBackPointer();
|
| + }
|
| + /// Initialize() binds the <code>CallbackFactory</code> to a particular
|
| + /// object. Use this when the object is not available at
|
| + /// <code>CallbackFactory</code> creation, and the <code>NULL</code> default
|
| + /// is passed to the constructor. The object may only be initialized once,
|
| + /// either by the constructor, or by a call to Initialize().
|
| + ///
|
| + /// @param[in] object The object whose member functions are to be bound to
|
| + /// the <code>CompletionCallback</code> created by this
|
| + /// <code>CompletionCallbackFactory</code>.
|
| + void Initialize(T* object) {
|
| + PP_DCHECK(object);
|
| + PP_DCHECK(!object_); // May only initialize once!
|
| + object_ = object;
|
| + }
|
| +
|
| + /// GetObject() returns the object that was passed at initialization to
|
| + /// Intialize().
|
| + ///
|
| + /// @return the object passed to the constructor or Intialize().
|
| + T* GetObject() {
|
| + return object_;
|
| + }
|
| +
|
| + /// 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.
|
| + /// NewCallback() is equivalent to NewRequiredCallback() below.
|
| + ///
|
| + /// @param[in] method The method to be invoked upon completion of the
|
| + /// operation.
|
| + ///
|
| + /// @return A <code>CompletionCallback</code>.
|
| + template <typename Method>
|
| + CompletionCallback NewCallback(Method method) {
|
| + PP_DCHECK(object_);
|
| + return NewCallbackHelper(Dispatcher0<Method>(method));
|
| + }
|
| +
|
| + /// NewRequiredCallback() allocates a new, single-use
|
| + /// <code>CompletionCallback</code> that will always run. 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 Method>
|
| + CompletionCallback NewRequiredCallback(Method method) {
|
| + CompletionCallback cc = NewCallback(method);
|
| + cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
|
| + return cc;
|
| + }
|
| +
|
| + /// NewOptionalCallback() allocates a new, single-use
|
| + /// <code>CompletionCallback</code> that might not run if the method
|
| + /// taking it can complete synchronously. Thus, if after passing the
|
| + /// CompletionCallback to a Pepper method, the method does not return
|
| + /// PP_OK_COMPLETIONPENDING, then you should manually call the
|
| + /// CompletionCallback's Run method, or memory will be leaked.
|
| + ///
|
| + /// @param[in] method The method to be invoked upon completion of the
|
| + /// operation.
|
| + ///
|
| + /// @return A <code>CompletionCallback</code>.
|
| + template <typename Method>
|
| + CompletionCallback NewOptionalCallback(Method method) {
|
| + CompletionCallback cc = NewCallback(method);
|
| + cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
|
| + return cc;
|
| + }
|
| +
|
| + /// 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.
|
| + /// NewCallback() is equivalent to NewRequiredCallback() below.
|
| + ///
|
| + /// @param[in] method The method to be invoked upon completion of the
|
| + /// operation. Method should be of type:
|
| + /// <code>void (T::*)(int32_t result, const A& a)</code>
|
| + ///
|
| + /// @param[in] a Passed to <code>method</code> when the completion callback
|
| + /// runs.
|
| + ///
|
| + /// @return A <code>CompletionCallback</code>.
|
| + template <typename Method, typename A>
|
| + CompletionCallback NewCallback(Method method, const A& a) {
|
| + PP_DCHECK(object_);
|
| + return NewCallbackHelper(Dispatcher1<Method, A>(method, a));
|
| + }
|
| +
|
| + /// NewRequiredCallback() allocates a new, single-use
|
| + /// <code>CompletionCallback</code> that will always run. 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. Method should be of type:
|
| + /// <code>void (T::*)(int32_t result, const A& a)</code>
|
| + ///
|
| + /// @param[in] a Passed to <code>method</code> when the completion callback
|
| + /// runs.
|
| + ///
|
| + /// @return A <code>CompletionCallback</code>.
|
| + template <typename Method, typename A>
|
| + CompletionCallback NewRequiredCallback(Method method, const A& a) {
|
| + CompletionCallback cc = NewCallback(method, a);
|
| + cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
|
| + return cc;
|
| + }
|
| +
|
| + /// NewOptionalCallback() allocates a new, single-use
|
| + /// <code>CompletionCallback</code> that might not run if the method
|
| + /// taking it can complete synchronously. Thus, if after passing the
|
| + /// CompletionCallback to a Pepper method, the method does not return
|
| + /// PP_OK_COMPLETIONPENDING, then you should manually call the
|
| + /// CompletionCallback's Run method, or memory will be leaked.
|
| + ///
|
| + /// @param[in] method The method to be invoked upon completion of the
|
| + /// operation. Method should be of type:
|
| + /// <code>void (T::*)(int32_t result, const A& a)</code>
|
| + ///
|
| + /// @param[in] a Passed to <code>method</code> when the completion callback
|
| + /// runs.
|
| + ///
|
| + /// @return A <code>CompletionCallback</code>.
|
| + template <typename Method, typename A>
|
| + CompletionCallback NewOptionalCallback(Method method, const A& a) {
|
| + CompletionCallback cc = NewCallback(method, a);
|
| + cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
|
| + return cc;
|
| + }
|
| +
|
| + /// 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.
|
| + /// NewCallback() is equivalent to NewRequiredCallback() below.
|
| + ///
|
| + /// @param method The method taking the callback. Method should be of type:
|
| + /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code>
|
| + ///
|
| + /// @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 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));
|
| + }
|
| +
|
| + /// NewRequiredCallback() allocates a new, single-use
|
| + /// <code>CompletionCallback</code> that will always run. The
|
| + /// <code>CompletionCallback</code> must be run in order for the memory
|
| + /// allocated by the methods to be freed.
|
| + ///
|
| + /// @param method The method taking the callback. Method should be of type:
|
| + /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code>
|
| + ///
|
| + /// @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 Method, typename A, typename B>
|
| + CompletionCallback NewRequiredCallback(Method method, const A& a,
|
| + const B& b) {
|
| + CompletionCallback cc = NewCallback(method, a, b);
|
| + cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
|
| + return cc;
|
| + }
|
| +
|
| + /// NewOptionalCallback() allocates a new, single-use
|
| + /// <code>CompletionCallback</code> that might not run if the method
|
| + /// taking it can complete synchronously. Thus, if after passing the
|
| + /// CompletionCallback to a Pepper method, the method does not return
|
| + /// PP_OK_COMPLETIONPENDING, then you should manually call the
|
| + /// CompletionCallback's Run method, or memory will be leaked.
|
| + ///
|
| + /// @param[in] method The method taking the callback. Method should be of
|
| + /// type:
|
| + /// <code>void (T::*)(int32_t result, const A& a, const B& b)</code>
|
| + ///
|
| + /// @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 Method, typename A, typename B>
|
| + CompletionCallback NewOptionalCallback(Method method, const A& a,
|
| + const B& b) {
|
| + CompletionCallback cc = NewCallback(method, a, b);
|
| + cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
|
| + return cc;
|
| + }
|
| +
|
| + /// 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.
|
| + /// NewCallback() is equivalent to NewRequiredCallback() below.
|
| + ///
|
| + /// @param method The method taking the callback. Method should be of type:
|
| + /// <code>
|
| + /// void (T::*)(int32_t result, const A& a, const B& b, const C& c)
|
| + /// </code>
|
| + ///
|
| + /// @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 Method, typename A, typename B, typename C>
|
| + 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));
|
| + }
|
| +
|
| + /// NewRequiredCallback() allocates a new, single-use
|
| + /// <code>CompletionCallback</code> that will always run. The
|
| + /// <code>CompletionCallback</code> must be run in order for the memory
|
| + /// allocated by the methods to be freed.
|
| + ///
|
| + /// @param method The method taking the callback. Method should be of type:
|
| + /// <code>
|
| + /// void (T::*)(int32_t result, const A& a, const B& b, const C& c)
|
| + /// </code>
|
| + ///
|
| + /// @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 Method, typename A, typename B, typename C>
|
| + CompletionCallback NewRequiredCallback(Method method, const A& a,
|
| + const B& b, const C& c) {
|
| + CompletionCallback cc = NewCallback(method, a, b, c);
|
| + cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
|
| + return cc;
|
| + }
|
| +
|
| + /// NewOptionalCallback() allocates a new, single-use
|
| + /// <code>CompletionCallback</code> that might not run if the method
|
| + /// taking it can complete synchronously. Thus, if after passing the
|
| + /// CompletionCallback to a Pepper method, the method does not return
|
| + /// PP_OK_COMPLETIONPENDING, then you should manually call the
|
| + /// CompletionCallback's Run method, or memory will be leaked.
|
| + ///
|
| + /// @param[in] method The method taking the callback. Method should be of
|
| + /// type:
|
| + /// <code>
|
| + /// void (T::*)(int32_t result, const A& a, const B& b, const C& c)
|
| + /// </code>
|
| + ///
|
| + /// @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 Method, typename A, typename B, typename C>
|
| + CompletionCallback NewOptionalCallback(Method method, const A& a,
|
| + const B& b, const C& c) {
|
| + CompletionCallback cc = NewCallback(method, a, b, c);
|
| + cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
|
| + return cc;
|
| + }
|
| +
|
| + private:
|
| + class BackPointer {
|
| + public:
|
| + typedef CompletionCallbackFactory<T, RefCount> FactoryType;
|
| +
|
| + BackPointer(FactoryType* factory)
|
| + : factory_(factory) {
|
| + }
|
| +
|
| + void AddRef() {
|
| + ref_.AddRef();
|
| + }
|
| +
|
| + void Release() {
|
| + if (ref_.Release() == 0)
|
| + delete this;
|
| + }
|
| +
|
| + void DropFactory() {
|
| + factory_ = NULL;
|
| + }
|
| +
|
| + T* GetObject() {
|
| + return factory_ ? factory_->GetObject() : NULL;
|
| + }
|
| +
|
| + private:
|
| + RefCount ref_;
|
| + FactoryType* factory_;
|
| + };
|
| +
|
| + template <typename Dispatcher>
|
| + class CallbackData {
|
| + public:
|
| + CallbackData(BackPointer* back_pointer, const Dispatcher& dispatcher)
|
| + : back_pointer_(back_pointer),
|
| + dispatcher_(dispatcher) {
|
| + back_pointer_->AddRef();
|
| + }
|
| +
|
| + ~CallbackData() {
|
| + back_pointer_->Release();
|
| + }
|
| +
|
| + 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);
|
| + delete self;
|
| + }
|
| +
|
| + private:
|
| + typedef CallbackData<Dispatcher> Self;
|
| + BackPointer* back_pointer_;
|
| + Dispatcher dispatcher_;
|
| + };
|
| +
|
| + template <typename Method>
|
| + class Dispatcher0 {
|
| + public:
|
| + Dispatcher0(Method method) : method_(method) {
|
| + }
|
| + void operator()(T* object, int32_t result) {
|
| + (object->*method_)(result);
|
| + }
|
| + private:
|
| + Method method_;
|
| + };
|
| +
|
| + template <typename Method, typename A>
|
| + class Dispatcher1 {
|
| + public:
|
| + Dispatcher1(Method method, const A& a)
|
| + : method_(method),
|
| + a_(a) {
|
| + }
|
| + void operator()(T* object, int32_t result) {
|
| + (object->*method_)(result, a_);
|
| + }
|
| + private:
|
| + Method method_;
|
| + A a_;
|
| + };
|
| +
|
| + template <typename Method, typename A, typename B>
|
| + class Dispatcher2 {
|
| + public:
|
| + Dispatcher2(Method method, const A& a, const B& b)
|
| + : method_(method),
|
| + a_(a),
|
| + b_(b) {
|
| + }
|
| + void operator()(T* object, int32_t result) {
|
| + (object->*method_)(result, a_, b_);
|
| + }
|
| + private:
|
| + Method method_;
|
| + A a_;
|
| + B b_;
|
| + };
|
| +
|
| + template <typename Method, typename A, typename B, typename C>
|
| + class Dispatcher3 {
|
| + public:
|
| + Dispatcher3(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, a_, b_, c_);
|
| + }
|
| + private:
|
| + Method method_;
|
| + A a_;
|
| + B b_;
|
| + C c_;
|
| + };
|
| +
|
| + void InitBackPointer() {
|
| + back_pointer_ = new BackPointer(this);
|
| + back_pointer_->AddRef();
|
| + }
|
| +
|
| + void ResetBackPointer() {
|
| + back_pointer_->DropFactory();
|
| + back_pointer_->Release();
|
| + }
|
| +
|
| + template <typename Dispatcher>
|
| + CompletionCallback NewCallbackHelper(const Dispatcher& dispatcher) {
|
| + PP_DCHECK(object_); // Expects a non-null object!
|
| + return CompletionCallback(
|
| + &CallbackData<Dispatcher>::Thunk,
|
| + new CallbackData<Dispatcher>(back_pointer_, dispatcher));
|
| + }
|
| +
|
| + // Disallowed:
|
| + CompletionCallbackFactory(const CompletionCallbackFactory&);
|
| + CompletionCallbackFactory& operator=(const CompletionCallbackFactory&);
|
| +
|
| + T* object_;
|
| + BackPointer* back_pointer_;
|
| +};
|
| +
|
| +} // namespace pp
|
| +
|
| +#endif // PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_
|
|
|