// Copyright (c) 2012 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/module.h" #include "ppapi/cpp/output_traits.h" struct PP_ArrayOutput; /// @file /// This file defines the API to create and run a callback. namespace pp { template class AsyncArrayOutputAdapter; template class AsyncResourceArrayOutputAdapter; /// This API enables you to implement and receive callbacks when /// Pepper operations complete asynchronously. /// /// You can create these objects yourself, but it is most common to use the /// CompletionCallbackFactory to allow the callbacks to call class member /// functions. class CompletionCallback { public: /// 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. /// /// Note: Blocking completion callbacks are only allowed from /// from background threads. 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; } /// 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 same thread where the PPB method was invoked. /// /// @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; } /// 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; // FIXME(dmichael): Use pp::MessageLoop here once it's out of Dev. Module::Get()->core()->CallOnMainThread(0, *this, result); return PP_OK_COMPLETIONPENDING; } protected: PP_CompletionCallback cc_; }; /// A CompletionCallbackWithOutput defines a completion callback that /// additionally stores a pointer to some output data. Some C++ wrappers /// take a CompletionCallbackWithOutput when the browser is returning a /// bit of data as part of the function call. The "output" parameter /// stored in the CompletionCallbackWithOutput will receive the data from /// the browser. /// /// You can create this yourself, but it is most common to use with the /// CompletionCallbackFactory's NewCallbackWithOutput, which manages the /// storage for the output parameter for you and passes it as an argument /// to your callback function. /// /// Note that this class doesn't actually do anything with the output data, /// it just stores a pointer to it. C++ wrapper objects that accept a /// CompletionCallbackWithOutput will retrieve this pointer and pass it to /// the browser as the output parameter. template class CompletionCallbackWithOutput : public CompletionCallback { public: /// The type that will actually be stored in the completion callback. In the /// common case, this will be equal to the template parameter (for example, /// CompletionCallbackWithOutput would obviously take an int*. However, /// resources are passed as PP_Resource, vars as PP_Var, and arrays as our /// special ArrayOutputAdapter object. The CallbackOutputTraits defines /// specializations for all of these cases. typedef typename internal::CallbackOutputTraits::StorageType OutputStorageType; typedef typename internal::CallbackOutputTraits::APIArgType APIArgType; /// The default constructor will create a blocking /// CompletionCallback that references the given output /// data. /// /// @param[in] output A pointer to the data associated with the callback. The /// caller must ensure that this pointer outlives the completion callback. /// /// Note: Blocking completion callbacks are only allowed from /// from background threads. CompletionCallbackWithOutput(OutputStorageType* output) : CompletionCallback(), output_(output) { } /// A constructor for creating a CompletionCallback that /// references the given output data. /// /// @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] output A pointer to the data associated with the callback. The /// caller must ensure that this pointer outlives the completion callback. CompletionCallbackWithOutput(PP_CompletionCallback_Func func, void* user_data, OutputStorageType* output) : CompletionCallback(func, user_data), output_(output) { } /// A constructor for creating a CompletionCallback that /// references the given output data. /// /// @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. /// /// @param[in] output A pointer to the data associated with the callback. The /// caller must ensure that this pointer outlives the completion callback. CompletionCallbackWithOutput(PP_CompletionCallback_Func func, void* user_data, int32_t flags, OutputStorageType* output) : CompletionCallback(func, user_data, flags), output_(output) { } APIArgType output() const { return internal::CallbackOutputTraits::StorageToAPIArg(*output_); } private: OutputStorageType* output_; }; /// 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. inline CompletionCallback BlockUntilComplete() { // Note: Explicitly inlined to avoid link errors when included into // ppapi_proxy and ppapi_cpp_objects. return CompletionCallback(); } } // namespace pp #endif // PPAPI_CPP_COMPLETION_CALLBACK_H_