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_ |