From 3a9bcbf8625df86ec726b64036b39595625978c9 Mon Sep 17 00:00:00 2001 From: "jond@google.com" Date: Mon, 22 Aug 2011 19:41:00 +0000 Subject: I think I need a rubber stamp LGTM from you. Review URL: http://codereview.chromium.org/7565016 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@97713 0039d316-1c4b-4281-b951-d872f2087c98 --- ppapi/cpp/completion_callback.h | 447 +++++++++++++++++++++++++++++----------- 1 file changed, 322 insertions(+), 125 deletions(-) (limited to 'ppapi/cpp/completion_callback.h') diff --git a/ppapi/cpp/completion_callback.h b/ppapi/cpp/completion_callback.h index 49f8d8f..797fb83 100644 --- a/ppapi/cpp/completion_callback.h +++ b/ppapi/cpp/completion_callback.h @@ -10,62 +10,130 @@ #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 { -// A CompletionCallback provides a wrapper around PP_CompletionCallback. +/// This API enables you to implement and receive callbacks when +/// Pepper operations complete asynchronously. class CompletionCallback { public: - // The default constructor will create a 'blocking' CompletionCallback - // that may be passed to a method to indicate that the calling thread should - // be blocked until the asynchronous operation corresponding to the method - // completes. + /// The default constructor will create a blocking + /// CompletionCallback 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. CompletionCallback() { cc_ = PP_BlockUntilComplete(); } + /// A constructor for creating a CompletionCallback. + /// + /// @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 CompletionCallback 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 + /// PP_CompletionCallback_Flag 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 + /// PP_CompletionCallback_Flag flags used to control how + /// non-NULL callbacks are scheduled by asynchronous methods. void set_flags(int32_t flags) { cc_.flags = flags; } - // Call this method to explicitly run the CompletionCallback. Normally, the - // system runs a CompletionCallback after an asynchronous operation - // completes, but programs may wish to run the CompletionCallback manually - // in order to reuse the same code paths. + /// Run() is used to run the CompletionCallback. + /// Normally, the system runs a CompletionCallback after an + /// asynchronous operation completes, but programs may wish to run the + /// CompletionCallback 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 pp_errors.h (excluding + /// PP_OK_COMPLETIONPENDING). 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 + /// PP_COMPLETIONCALLBACK_FLAG_OPTIONAL 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 + /// PP_CompletionCallback + /// + /// @return A PP_CompletionCallback. 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 + /// PP_CompletionCallback_Flag flags. int32_t flags() const { return cc_.flags; } - // Use this when implementing functions taking callbacks. - // If the callback is required and |result| indicates that it has not - // been scheduled, it will be forced on the main thread. - // - // EXAMPLE USAGE: - // - // 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); - // } - // + /// MayForce() is used when implementing functions taking callbacks. + /// If the callback is required and result indicates that it has + /// not been scheduled, it will be forced on the main thread. + /// + /// Example: + /// + /// @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 + /// pp_errors.h. Positive values indicate additional information + /// such as bytes read. + /// + /// @return PP_OK_COMPLETIONPENDING if the callback has been + /// forced, result parameter otherwise. int32_t MayForce(int32_t result) const { if (result == PP_OK_COMPLETIONPENDING || IsOptional()) return result; @@ -77,130 +145,170 @@ class CompletionCallback { PP_CompletionCallback cc_; }; -// Create a 'blocking' CompletionCallback. +/// 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 CompletionCallback corresponding to a NULL callback. CompletionCallback BlockUntilComplete(); -// CompletionCallbackFactory 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. -// -// NOTE: by default, CompletionCallbackFactory 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 CompletionCallbackFactory on -// the main thread, create callbacks from any thread and pass them to -// CallOnMainThread. -// -// EXAMPLE USAGE: -// -// class MyHandler { -// public: -// 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 factory_; -// pp::FileIO fio_; -// char buf_[4096]; -// int64_t offset_; -// }; -// +/// CompletionCallbackFactory 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. +/// +/// Note: CompletionCallbackFactory 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 CompletionCallbackFactory on the main thread, create +/// callbacks from any thread and pass them to CallOnMainThread(). +/// +/// Example: +/// +/// @code +/// +/// class MyHandler { +/// public: +/// 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 factory_; +/// pp::FileIO fio_; +/// char buf_[4096]; +/// int64_t offset_; +/// }; +/// +/// @endcode +/// template class CompletionCallbackFactory { public: + + /// This constructor creates a CompletionCallbackFactory + /// bound to an object. If the constructor is called without an argument, + /// the default value of NULL 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 + /// CompletionCallbackFactory. The default value of this + /// parameter is NULL. explicit CompletionCallbackFactory(T* object = NULL) : object_(object) { InitBackPointer(); } + /// Destructor. ~CompletionCallbackFactory() { ResetBackPointer(); } - // Cancels all CompletionCallbacks allocated from this factory. + /// CancelAll() cancels all CompletionCallbacks allocated from + /// this factory. void CancelAll() { ResetBackPointer(); InitBackPointer(); } - + /// Initialize() binds the CallbackFactory to a particular + /// object. Use this when the object is not available at + /// CallbackFactory creation, and the NULL 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 CompletionCallback created by this + /// CompletionCallbackFactory. 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_; } - // Methods for allocating new, single-use CompletionCallbacks. - // The CompletionCallback must be run in order for the memory - // allocated by the methods to be freed. - // NewRequiredCallback() creates callbacks that will always run. - // NewOptionalCallback() creates callbacks that might not run if the method - // taking them can complete synchronously. Thus, if after passing the - // CompletionCallback to a PPAPI method, the method does not return - // PP_OK_COMPLETIONPENDING, then you should manually call the - // CompletionCallback's Run method, or memory will be leaked. - // NewCallback() is equivalent to NewRequiredCallback(). - + /// NewCallback allocates a new, single-use CompletionCallback. + /// The CompletionCallback 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 CompletionCallback. template CompletionCallback NewCallback(Method method) { PP_DCHECK(object_); return NewCallbackHelper(Dispatcher0(method)); } + /// NewRequiredCallback() allocates a new, single-use + /// CompletionCallback that will always run. The + /// CompletionCallback 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 CompletionCallback. template CompletionCallback NewRequiredCallback(Method method) { CompletionCallback cc = NewCallback(method); @@ -208,6 +316,17 @@ class CompletionCallbackFactory { return cc; } + /// NewOptionalCallback() allocates a new, single-use + /// CompletionCallback 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 CompletionCallback. template CompletionCallback NewOptionalCallback(Method method) { CompletionCallback cc = NewCallback(method); @@ -215,18 +334,38 @@ class CompletionCallbackFactory { return cc; } - // A copy of "a" will be passed to "method" when the completion callback - // runs. - // - // Method should be of type: - // void (T::*)(int32_t result, const A& a) - // + /// NewCallback() allocates a new, single-use CompletionCallback. + /// The CompletionCallback 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: + /// void (T::*)(int32_t result, const A& a) + /// + /// @param[in] a Passed to method when the completion callback + /// runs. + /// + /// @return A CompletionCallback. template CompletionCallback NewCallback(Method method, const A& a) { PP_DCHECK(object_); return NewCallbackHelper(Dispatcher1(method, a)); } + /// NewRequiredCallback() allocates a new, single-use + /// CompletionCallback that will always run. The + /// CompletionCallback 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: + /// void (T::*)(int32_t result, const A& a) + /// + /// @param[in] a Passed to method when the completion callback + /// runs. + /// + /// @return A CompletionCallback. template CompletionCallback NewRequiredCallback(Method method, const A& a) { CompletionCallback cc = NewCallback(method, a); @@ -234,6 +373,21 @@ class CompletionCallbackFactory { return cc; } + /// NewOptionalCallback() allocates a new, single-use + /// CompletionCallback 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: + /// void (T::*)(int32_t result, const A& a) + /// + /// @param[in] a Passed to method when the completion callback + /// runs. + /// + /// @return A CompletionCallback. template CompletionCallback NewOptionalCallback(Method method, const A& a) { CompletionCallback cc = NewCallback(method, a); @@ -241,18 +395,43 @@ class CompletionCallbackFactory { return cc; } - // A copy of "a" and "b" will be passed to "method" when the completion - // callback runs. - // - // Method should be of type: - // void (T::*)(int32_t result, const A& a, const B& b) - // + /// NewCallback() allocates a new, single-use + /// CompletionCallback. + /// The CompletionCallback 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: + /// void (T::*)(int32_t result, const A& a, const B& b) + /// + /// @param[in] a Passed to method when the completion callback + /// runs. + /// + /// @param[in] b Passed to method when the completion callback + /// runs. + /// + /// @return A CompletionCallback. template CompletionCallback NewCallback(Method method, const A& a, const B& b) { PP_DCHECK(object_); return NewCallbackHelper(Dispatcher2(method, a, b)); } + /// NewRequiredCallback() allocates a new, single-use + /// CompletionCallback that will always run. The + /// CompletionCallback 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: + /// void (T::*)(int32_t result, const A& a, const B& b) + /// + /// @param[in] a Passed to method when the completion callback + /// runs. + /// + /// @param[in] b Passed to method when the completion callback + /// runs. + /// + /// @return A CompletionCallback. template CompletionCallback NewRequiredCallback(Method method, const A& a, const B& b) { @@ -261,6 +440,24 @@ class CompletionCallbackFactory { return cc; } + /// NewOptionalCallback() allocates a new, single-use + /// CompletionCallback 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: + /// void (T::*)(int32_t result, const A& a, const B& b) + /// + /// @param[in] a Passed to method when the completion callback + /// runs. + /// + /// @param[in] b Passed to method when the completion callback + /// runs. + /// + /// @return A CompletionCallback. template CompletionCallback NewOptionalCallback(Method method, const A& a, const B& b) { -- cgit v1.1