summaryrefslogtreecommitdiffstats
path: root/ppapi/cpp/completion_callback.h
diff options
context:
space:
mode:
authorpolina@google.com <polina@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-30 21:42:37 +0000
committerpolina@google.com <polina@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-30 21:42:37 +0000
commit917e86adc3f824f518c999dcba20bfd4cbf18a18 (patch)
tree52fe38f61527360231c17a905015066fb5d34bba /ppapi/cpp/completion_callback.h
parent9ae7b9195f0e06b64664bba52e9cc0e8b3470f56 (diff)
downloadchromium_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.h105
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: