Index: ppapi/cpp/completion_callback.h |
=================================================================== |
--- ppapi/cpp/completion_callback.h (revision 116706) |
+++ ppapi/cpp/completion_callback.h (working copy) |
@@ -8,7 +8,7 @@ |
#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" |
+#include "ppapi/cpp/module.h" |
/// @file |
/// This file defines the API to create and run a callback. |
@@ -156,555 +156,6 @@ |
/// @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_ |