diff options
author | polina@google.com <polina@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-30 21:42:37 +0000 |
---|---|---|
committer | polina@google.com <polina@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-30 21:42:37 +0000 |
commit | 917e86adc3f824f518c999dcba20bfd4cbf18a18 (patch) | |
tree | 52fe38f61527360231c17a905015066fb5d34bba /ppapi/cpp/completion_callback.h | |
parent | 9ae7b9195f0e06b64664bba52e9cc0e8b3470f56 (diff) | |
download | chromium_src-917e86adc3f824f518c999dcba20bfd4cbf18a18.zip chromium_src-917e86adc3f824f518c999dcba20bfd4cbf18a18.tar.gz chromium_src-917e86adc3f824f518c999dcba20bfd4cbf18a18.tar.bz2 |
Add a flag field to PP_CompletionCallback to control if the callback should
always be invoked asynchronously on success or error or skipped if the
operation can complete synchronously without blocking. Keep the default
behavior as-is until clients update their code. Bump revisions of all
interfaces that take callbacks as args. Update browser interface function
implementations and C++ layer to force callbacks if sync option is not set.
Change ppapi/tests to run tests involving callbacks with both flag options.
BUG=79376
TEST=ppapi_tests + bots
Review URL: http://codereview.chromium.org/6899055
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@91205 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/cpp/completion_callback.h')
-rw-r--r-- | ppapi/cpp/completion_callback.h | 105 |
1 files changed, 96 insertions, 9 deletions
diff --git a/ppapi/cpp/completion_callback.h b/ppapi/cpp/completion_callback.h index 92403f3..6438c07 100644 --- a/ppapi/cpp/completion_callback.h +++ b/ppapi/cpp/completion_callback.h @@ -6,6 +6,7 @@ #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" @@ -27,6 +28,14 @@ class CompletionCallback { cc_ = PP_MakeCompletionCallback(func, user_data); } + CompletionCallback(PP_CompletionCallback_Func func, void* user_data, + int32_t flags) { + cc_ = PP_MakeCompletionCallback(func, user_data); + cc_.flags = flags; + } + + 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 @@ -36,7 +45,34 @@ class CompletionCallback { PP_RunCompletionCallback(&cc_, result); } + bool IsOptional() const { + return (cc_.func == NULL || + (cc_.flags & PP_COMPLETIONCALLBACK_FLAG_OPTIONAL) != 0); + } + const PP_CompletionCallback& pp_completion_callback() const { return cc_; } + 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); + // } + // + 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_; @@ -67,10 +103,10 @@ class CompletionCallback { // } // // void ProcessFile(const FileRef& file) { -// CompletionCallback cc = factory_.NewCallback(&MyHandler::DidOpen); +// CompletionCallback cc = factory_.NewRequiredCallback( +// &MyHandler::DidOpen); // int32_t rv = fio_.Open(file, PP_FileOpenFlag_Read, cc); -// if (rv != PP_OK_COMPLETIONPENDING) -// cc.Run(rv); +// CHECK(rv == PP_OK_COMPLETIONPENDING); // } // // private: @@ -100,7 +136,8 @@ class CompletionCallback { // } // // void ReadMore() { -// CompletionCallback cc = factory_.NewCallback(&MyHandler::DidRead); +// CompletionCallback cc = +// factory_.NewOptionalCallback(&MyHandler::DidRead); // int32_t rv = fio_.Read(offset_, buf_, sizeof(buf_), // cc.pp_completion_callback()); // if (rv != PP_OK_COMPLETIONPENDING) @@ -145,11 +182,17 @@ class CompletionCallbackFactory { return object_; } - // Allocates a new, single-use CompletionCallback. The CompletionCallback - // must be run in order for the memory allocated by NewCallback to be freed. - // 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 otherwise memory will be leaked. + // 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 NewOptionalCallback(). + // TODO(polina): update this comment when this is no longer true. template <typename Method> CompletionCallback NewCallback(Method method) { @@ -157,6 +200,20 @@ class CompletionCallbackFactory { return NewCallbackHelper(Dispatcher0<Method>(method)); } + template <typename Method> + CompletionCallback NewRequiredCallback(Method method) { + CompletionCallback cc = NewCallback(method); + cc.set_flags(cc.flags() & ~PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); + return cc; + } + + template <typename Method> + CompletionCallback NewOptionalCallback(Method method) { + CompletionCallback cc = NewCallback(method); + cc.set_flags(cc.flags() | PP_COMPLETIONCALLBACK_FLAG_OPTIONAL); + return cc; + } + // A copy of "a" will be passed to "method" when the completion callback // runs. // @@ -169,6 +226,20 @@ class CompletionCallbackFactory { return NewCallbackHelper(Dispatcher1<Method, A>(method, a)); } + 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; + } + + 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; + } + // A copy of "a" and "b" will be passed to "method" when the completion // callback runs. // @@ -181,6 +252,22 @@ class CompletionCallbackFactory { return NewCallbackHelper(Dispatcher2<Method, A, B>(method, a, b)); } + 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; + } + + 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; + } + private: class BackPointer { public: |