text: // 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/extensions/ext_output_traits.h"
  #include "ppapi/cpp/logging.h"
  #include "ppapi/cpp/module.h"
  #include "ppapi/cpp/output_traits.h"
  
  /// @file
  /// This file defines the API to create and run a callback.
  namespace pp {
  
  /// 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
    /// <code>CompletionCallback</code> 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.
    ///
    /// <strong>Note:</strong> Blocking completion callbacks are only allowed from
    /// from background threads.
    CompletionCallback() {
      cc_ = PP_BlockUntilComplete();
    }
  
    /// A constructor for creating a <code>CompletionCallback</code>.
    ///
    /// @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 <code>CompletionCallback</code> 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
    /// <code>PP_CompletionCallback_Flag</code> 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
    /// <code>PP_CompletionCallback_Flag</code> 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 <code>CompletionCallback</code>.
    /// Normally, the system runs a <code>CompletionCallback</code> after an
    /// asynchronous operation completes, but programs may wish to run the
    /// <code>CompletionCallback</code> 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 <code>pp_errors.h</code> (excluding
    /// <code>PP_OK_COMPLETIONPENDING</code>). 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
    /// <code>PP_COMPLETIONCALLBACK_FLAG_OPTIONAL</code> 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
    /// <code>PP_CompletionCallback</code>
    ///
    /// @return A <code>PP_CompletionCallback</code>.
    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
    /// <code>PP_CompletionCallback_Flag</code> flags.
    int32_t flags() const { return cc_.flags; }
  
    /// MayForce() is used when implementing functions taking callbacks.
    /// If the callback is required and <code>result</code> indicates that it has
    /// not been scheduled, it will be forced on the main thread.
    ///
    /// <strong>Example:</strong>
    ///
    /// @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
    /// <code>pp_errors.h</code>. Positive values indicate additional information
    /// such as bytes read.
    ///
    /// @return <code>PP_OK_COMPLETIONPENDING</code> 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_;
  };
  
  namespace internal {
  
  /// The base class of [Ext]CompletionCallbackWithOutput.
  ///
  /// The template parameter Traits determines the storage type
  /// (OutputStorageType), the output parameter type used by the browser
  /// (APIArgType), and how to map OutputStorageType to APIArgType.
  template <typename T, typename Traits>
  class CompletionCallbackWithOutputBase : public CompletionCallback {
   public:
    typedef typename Traits::StorageType OutputStorageType;
    typedef typename Traits::APIArgType APIArgType;
    typedef Traits TraitsType;
  
    explicit CompletionCallbackWithOutputBase(OutputStorageType* output)
        : CompletionCallback(),
          output_(output) {
    }
  
    CompletionCallbackWithOutputBase(PP_CompletionCallback_Func func,
                                     void* user_data,
                                     OutputStorageType* output)
        : CompletionCallback(func, user_data),
          output_(output) {
    }
  
    CompletionCallbackWithOutputBase(PP_CompletionCallback_Func func,
                                     void* user_data,
                                     int32_t flags,
                                     OutputStorageType* output)
        : CompletionCallback(func, user_data, flags),
          output_(output) {
    }
  
    APIArgType output() const {
      return Traits::StorageToAPIArg(*output_);
    }
  
   private:
    OutputStorageType* output_;
  };
  
  }  // namespace internal
  
  /// 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 <typename T>
  class CompletionCallbackWithOutput
      : public internal::CompletionCallbackWithOutputBase<
          T, internal::CallbackOutputTraits<T> > {
   public:
    typedef internal::CompletionCallbackWithOutputBase<
        T, internal::CallbackOutputTraits<T> > BaseType;
  
    /// The default constructor will create a blocking
    /// <code>CompletionCallbackWithOutput</code> 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.
    /// In the common case, <code>OutputStorageType</code> will be equal to the
    /// template parameter T (for example,
    /// <code>CompletionCallbackWithOutput<int></code> would obviously take an
    /// int*. However, resources are passed as PP_Resource, vars as PP_Var, and
    /// arrays as our special ArrayOutputAdapter object.
    /// <code>internal::CallbackOutputTraits</code> defines specializations for
    /// all of these cases.
    ///
    /// <strong>Note:</strong> Blocking completion callbacks are only allowed from
    /// background threads.
    explicit CompletionCallbackWithOutput(
        typename BaseType::OutputStorageType* output)
        : BaseType(output) {
    }
  
    /// A constructor for creating a <code>CompletionCallbackWithOutput</code>
    /// 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,
                                 typename BaseType::OutputStorageType* output)
        : BaseType(func, user_data, output) {
    }
  
    /// A constructor for creating a <code>CompletionCallbackWithOutput</code>
    /// 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
    /// <code>PP_CompletionCallback_Flag</code> 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,
                                 typename BaseType::OutputStorageType* output)
        : BaseType(func, user_data, flags, output) {
    }
  };
  
  namespace ext {
  
  /// ExtCompletionCallbackWithOutput is similar to CompletionCallbackWithOutput,
  /// but used by APIs within the pp::ext namespace. Usually it is used with the
  /// CompletionCallbackFactory's NewExtCallbackWithOutput.
  template <typename T>
  class ExtCompletionCallbackWithOutput
      : public ::pp::internal::CompletionCallbackWithOutputBase<
          T, internal::ExtCallbackOutputTraits<T> > {
   public:
    typedef ::pp::internal::CompletionCallbackWithOutputBase<
        T, internal::ExtCallbackOutputTraits<T> > BaseType;
  
    /// The default constructor will create a blocking
    /// <code>ExtCompletionCallbackWithOutput</code> 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.
    /// <code>OutputStorageType</code> is either
    /// <code>ext::internal::ArrayVarOutputAdapterWithStorage<U></code> (if the
    /// template parameter T is of the form std::vector<U>) or
    /// <code>ext::internal::VarOutputAdapterWithStorage<T></code> (otherwise).
    ///
    /// <strong>Note:</strong> Blocking completion callbacks are only allowed from
    /// background threads.
    explicit ExtCompletionCallbackWithOutput(
        typename BaseType::OutputStorageType* output)
        : BaseType(output) {
    }
  
    /// A constructor for creating an <code>ExtCompletionCallbackWithOutput</code>
    /// 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.
    ExtCompletionCallbackWithOutput(PP_CompletionCallback_Func func,
                                    void* user_data,
                                    typename BaseType::OutputStorageType* output)
        : BaseType(func, user_data, output) {
    }
  
    /// A constructor for creating an <code>ExtCompletionCallbackWithOutput</code>
    /// 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
    /// <code>PP_CompletionCallback_Flag</code> 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.
    ExtCompletionCallbackWithOutput(PP_CompletionCallback_Func func,
                                    void* user_data,
                                    int32_t flags,
                                    typename BaseType::OutputStorageType* output)
        : BaseType(func, user_data, flags, output) {
    }
  };
  
  }  // namespace ext
  
  /// 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 <code>CompletionCallback</code> 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_
  