$$ This is a pump file for generating file templates.  Pump is a python
$$ script that is part of the Google Test suite of utilities.  Description
$$ can be found here:
$$
$$ http://code.google.com/p/googletest/wiki/PumpManual
$$

$$ See comment for MAX_ARITY in base/bind.h.pump.
$var MAX_ARITY = 7
$range ARITY 0..MAX_ARITY

// Copyright (c) 2011 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 BASE_BIND_INTERNAL_H_
#define BASE_BIND_INTERNAL_H_

#include "base/bind_helpers.h"
#include "base/callback_internal.h"
#include "base/memory/raw_scoped_refptr_mismatch_checker.h"
#include "base/memory/weak_ptr.h"
#include "base/template_util.h"
#include "build/build_config.h"

#if defined(OS_WIN)
#include "base/bind_internal_win.h"
#endif

namespace base {
namespace internal {

// See base/callback.h for user documentation.
//
//
// CONCEPTS:
//  Runnable -- A type (really a type class) that has a single Run() method
//              and a RunType typedef that corresponds to the type of Run().
//              A Runnable can declare that it should treated like a method
//              call by including a typedef named IsMethod.  The value of
//              this typedef is NOT inspected, only the existence.  When a
//              Runnable declares itself a method, Bind() will enforce special
//              refcounting + WeakPtr handling semantics for the first
//              parameter which is expected to be an object.
//  Functor -- A copyable type representing something that should be called.
//             All function pointers, Callback<>, and Runnables are functors
//             even if the invocation syntax differs.
//  RunType -- A function type (as opposed to function _pointer_ type) for
//             a Run() function.  Usually just a convenience typedef.
//  (Bound)ArgsType -- A function type that is being (ab)used to store the
//                     types of set of arguments.  The "return" type is always
//                     void here.  We use this hack so that we do not need
//                     a new type name for each arity of type. (eg.,
//                     BindState1, BindState2).  This makes forward
//                     declarations and friending much much easier.
//
// Types:
//  RunnableAdapter<> -- Wraps the various "function" pointer types into an
//                       object that adheres to the Runnable interface.
//                       There are |3*ARITY| RunnableAdapter types.
//  FunctionTraits<> -- Type traits that unwrap a function signature into a
//                      a set of easier to use typedefs.  Used mainly for
//                      compile time asserts.
//                      There are |ARITY| FunctionTraits types.
//  ForceVoidReturn<> -- Helper class for translating function signatures to
//                       equivalent forms with a "void" return type.
//                    There are |ARITY| ForceVoidReturn types.
//  FunctorTraits<> -- Type traits used determine the correct RunType and
//                     RunnableType for a Functor.  This is where function
//                     signature adapters are applied.
//                    There are |ARITY| ForceVoidReturn types.
//  MakeRunnable<> -- Takes a Functor and returns an object in the Runnable
//                    type class that represents the underlying Functor.
//                    There are |O(1)| MakeRunnable types.
//  InvokeHelper<> -- Take a Runnable + arguments and actully invokes it.
//                    Handle the differing syntaxes needed for WeakPtr<> support,
//                    and for ignoring return values.  This is separate from
//                    Invoker to avoid creating multiple version of Invoker<>
//                    which grows at O(n^2) with the arity.
//                    There are |k*ARITY| InvokeHelper types.
//  Invoker<> -- Unwraps the curried parameters and executes the Runnable.
//               There are |(ARITY^2 + ARITY)/2| Invoketypes.
//  BindState<> -- Stores the curried parameters, and is the main entry point
//                 into the Bind() system, doing most of the type resolution.
//                 There are ARITY BindState types.

// RunnableAdapter<>
//
// The RunnableAdapter<> templates provide a uniform interface for invoking
// a function pointer, method pointer, or const method pointer. The adapter
// exposes a Run() method with an appropriate signature. Using this wrapper
// allows for writing code that supports all three pointer types without
// undue repetition.  Without it, a lot of code would need to be repeated 3
// times.
//
// For method pointers and const method pointers the first argument to Run()
// is considered to be the received of the method.  This is similar to STL's
// mem_fun().
//
// This class also exposes a RunType typedef that is the function type of the
// Run() function.
//
// If and only if the wrapper contains a method or const method pointer, an
// IsMethod typedef is exposed.  The existence of this typedef (NOT the value)
// marks that the wrapper should be considered a method wrapper.

template <typename Functor>
class RunnableAdapter;

$for ARITY [[
$range ARG 1..ARITY

// Function: Arity $(ARITY).
template <typename R[[]]
$if ARITY > 0[[, ]] $for ARG , [[typename A$(ARG)]]>
class RunnableAdapter<R(*)($for ARG , [[A$(ARG)]])> {
 public:
  typedef R (RunType)($for ARG , [[A$(ARG)]]);

  explicit RunnableAdapter(R(*function)($for ARG , [[A$(ARG)]]))
      : function_(function) {
  }

  R Run($for ARG , [[typename CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) {
    return function_($for ARG , [[CallbackForward(a$(ARG))]]);
  }

 private:
  R (*function_)($for ARG , [[A$(ARG)]]);
};

// Method: Arity $(ARITY).
template <typename R, typename T[[]]
$if ARITY > 0[[, ]] $for ARG , [[typename A$(ARG)]]>
class RunnableAdapter<R(T::*)($for ARG , [[A$(ARG)]])> {
 public:
  typedef R (RunType)(T*[[]]
$if ARITY > 0[[, ]] $for ARG , [[A$(ARG)]]);
  typedef true_type IsMethod;

  explicit RunnableAdapter(R(T::*method)($for ARG , [[A$(ARG)]]))
      : method_(method) {
  }

  R Run(T* object[[]]
$if ARITY > 0[[, ]]  $for ARG, [[typename CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) {
    return (object->*method_)($for ARG , [[CallbackForward(a$(ARG))]]);
  }

 private:
  R (T::*method_)($for ARG , [[A$(ARG)]]);
};

// Const Method: Arity $(ARITY).
template <typename R, typename T[[]]
$if ARITY > 0[[, ]] $for ARG , [[typename A$(ARG)]]>
class RunnableAdapter<R(T::*)($for ARG , [[A$(ARG)]]) const> {
 public:
  typedef R (RunType)(const T*[[]]
$if ARITY > 0[[, ]] $for ARG , [[A$(ARG)]]);
  typedef true_type IsMethod;

  explicit RunnableAdapter(R(T::*method)($for ARG , [[A$(ARG)]]) const)
      : method_(method) {
  }

  R Run(const T* object[[]]
$if ARITY > 0[[, ]]  $for ARG, [[typename CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) {
    return (object->*method_)($for ARG , [[CallbackForward(a$(ARG))]]);
  }

 private:
  R (T::*method_)($for ARG , [[A$(ARG)]]) const;
};

]]  $$ for ARITY


// FunctionTraits<>
//
// Breaks a function signature apart into typedefs for easier introspection.
template <typename Sig>
struct FunctionTraits;

$for ARITY [[
$range ARG 1..ARITY

template <typename R[[]]
$if ARITY > 0[[, ]] $for ARG , [[typename A$(ARG)]]>
struct FunctionTraits<R($for ARG , [[A$(ARG)]])> {
  typedef R ReturnType;
$for ARG [[

  typedef A$(ARG) A$(ARG)Type;
]]

};

]]


// ForceVoidReturn<>
//
// Set of templates that support forcing the function return type to void.
template <typename Sig>
struct ForceVoidReturn;

$for ARITY [[
$range ARG 1..ARITY

template <typename R[[]]
$if ARITY > 0[[, ]] $for ARG , [[typename A$(ARG)]]>
struct ForceVoidReturn<R($for ARG , [[A$(ARG)]])> {
  typedef void(RunType)($for ARG , [[A$(ARG)]]);
};

]]  $$ for ARITY


// FunctorTraits<>
//
// See description at top of file.
template <typename T>
struct FunctorTraits {
  typedef RunnableAdapter<T> RunnableType;
  typedef typename RunnableType::RunType RunType;
};

template <typename T>
struct FunctorTraits<IgnoreResultHelper<T> > {
  typedef typename FunctorTraits<T>::RunnableType RunnableType;
  typedef typename ForceVoidReturn<
      typename RunnableType::RunType>::RunType RunType;
};

template <typename T>
struct FunctorTraits<Callback<T> > {
  typedef Callback<T> RunnableType;
  typedef typename Callback<T>::RunType RunType;
};


// MakeRunnable<>
//
// Converts a passed in functor to a RunnableType using type inference.

template <typename T>
typename FunctorTraits<T>::RunnableType MakeRunnable(const T& t) {
  return RunnableAdapter<T>(t);
}

template <typename T>
typename FunctorTraits<T>::RunnableType
MakeRunnable(const IgnoreResultHelper<T>& t) {
  return MakeRunnable(t.functor_);
}

template <typename T>
const typename FunctorTraits<Callback<T> >::RunnableType&
MakeRunnable(const Callback<T>& t) {
  return t;
}


// InvokeHelper<>
//
// There are 3 logical InvokeHelper<> specializations: normal, void-return,
// WeakCalls.
//
// The normal type just calls the underlying runnable.
//
// We need a InvokeHelper to handle void return types in order to support
// IgnoreResult().  Normally, if the Runnable's RunType had a void return,
// the template system would just accept "return functor.Run()" ignoring
// the fact that a void function is being used with return. This piece of
// sugar breaks though when the Runnable's RunType is not void.  Thus, we
// need a partial specialization to change the syntax to drop the "return"
// from the invocation call.
//
// WeakCalls similarly need special syntax that is applied to the first
// argument to check if they should no-op themselves.
template <bool IsWeakCall, typename ReturnType, typename Runnable,
          typename ArgsType>
struct InvokeHelper;

$for ARITY [[
$range ARG 1..ARITY

template <typename ReturnType, typename Runnable[[]]
$if ARITY > 0 [[,]] $for ARG , [[typename A$(ARG)]]>
struct InvokeHelper<false, ReturnType, Runnable,
    void($for ARG , [[A$(ARG)]])>  {
  static ReturnType MakeItSo(Runnable runnable[[]]
$if ARITY > 0[[, ]] $for ARG , [[A$(ARG) a$(ARG)]]) {
    return runnable.Run($for ARG , [[CallbackForward(a$(ARG))]]);
  }
};

template <typename Runnable[[]]
$if ARITY > 0 [[,]] $for ARG , [[typename A$(ARG)]]>
struct InvokeHelper<false, void, Runnable,
    void($for ARG , [[A$(ARG)]])>  {
  static void MakeItSo(Runnable runnable[[]]
$if ARITY > 0[[, ]] $for ARG , [[A$(ARG) a$(ARG)]]) {
    runnable.Run($for ARG , [[CallbackForward(a$(ARG))]]);
  }
};

$if ARITY > 0 [[

template <typename Runnable[[]], $for ARG , [[typename A$(ARG)]]>
struct InvokeHelper<true, void, Runnable,
    void($for ARG , [[A$(ARG)]])>  {
  static void MakeItSo(Runnable runnable[[]]
$if ARITY > 0[[, ]] $for ARG , [[A$(ARG) a$(ARG)]]) {
    if (!a1.get()) {
      return;
    }

    runnable.Run($for ARG , [[CallbackForward(a$(ARG))]]);
  }
};

]]

]] $$ for ARITY

#if !defined(_MSC_VER)

template <typename ReturnType, typename Runnable, typename ArgsType>
struct InvokeHelper<true, ReturnType, Runnable, ArgsType> {
  // WeakCalls are only supported for functions with a void return type.
  // Otherwise, the function result would be undefined if the the WeakPtr<>
  // is invalidated.
  COMPILE_ASSERT(is_void<ReturnType>::value,
                 weak_ptrs_can_only_bind_to_methods_without_return_values);
};

#endif

// Invoker<>
//
// See description at the top of the file.
template <int NumBound, typename Storage, typename RunType>
struct Invoker;

$for ARITY [[

$$ Number of bound arguments.
$range BOUND 0..ARITY
$for BOUND [[

$var UNBOUND = ARITY - BOUND
$range ARG 1..ARITY
$range BOUND_ARG 1..BOUND
$range UNBOUND_ARG (ARITY - UNBOUND + 1)..ARITY

// Arity $(ARITY) -> $(UNBOUND).
template <typename StorageType, typename R[[]]
$if ARITY > 0 [[,]][[]]
$for ARG , [[typename X$(ARG)]]>
struct Invoker<$(BOUND), StorageType, R($for ARG , [[X$(ARG)]])> {
  typedef R(RunType)(BindStateBase*[[]]
$if UNBOUND != 0 [[, ]]
$for UNBOUND_ARG , [[typename CallbackParamTraits<X$(UNBOUND_ARG)>::ForwardType]]);

  typedef R(UnboundRunType)($for UNBOUND_ARG , [[X$(UNBOUND_ARG)]]);

  static R Run(BindStateBase* base[[]]
$if UNBOUND != 0 [[, ]][[]]
$for UNBOUND_ARG , [[
typename CallbackParamTraits<X$(UNBOUND_ARG)>::ForwardType x$(UNBOUND_ARG)
]][[]]
) {
    StorageType* storage = static_cast<StorageType*>(base);

    // Local references to make debugger stepping easier. If in a debugger,
    // you really want to warp ahead and step through the
    // InvokeHelper<>::MakeItSo() call below.
$for BOUND_ARG
[[

    typedef typename StorageType::Bound$(BOUND_ARG)UnwrapTraits Bound$(BOUND_ARG)UnwrapTraits;
]]


$for BOUND_ARG
[[

    typename Bound$(BOUND_ARG)UnwrapTraits::ForwardType x$(BOUND_ARG) =
        Bound$(BOUND_ARG)UnwrapTraits::Unwrap(storage->p$(BOUND_ARG)_);
]]

    return InvokeHelper<StorageType::IsWeakCall::value, R,
           typename StorageType::RunnableType,
           void(
$for BOUND_ARG , [[
typename Bound$(BOUND_ARG)UnwrapTraits::ForwardType
]]

$if UNBOUND > 0 [[$if BOUND > 0 [[, ]]]][[]]

$for UNBOUND_ARG , [[
typename CallbackParamTraits<X$(UNBOUND_ARG)>::ForwardType x$(UNBOUND_ARG)
]]
)>
               ::MakeItSo(storage->runnable_
$if ARITY > 0[[, ]] $for ARG , [[CallbackForward(x$(ARG))]]);
  }
};

]] $$ for BOUND
]] $$ for ARITY


// BindState<>
//
// This stores all the state passed into Bind() and is also where most
// of the template resolution magic occurs.
//
// Runnable is the functor we are binding arguments to.
// RunType is type of the Run() function that the Invoker<> should use.
// Normally, this is the same as the RunType of the Runnable, but it can
// be different if an adapter like IgnoreResult() has been used.
//
// BoundArgsType contains the storage type for all the bound arguments by
// (ab)using a function type.
template <typename Runnable, typename RunType, typename BoundArgsType>
struct BindState;

$for ARITY [[
$range ARG 1..ARITY

template <typename Runnable, typename RunType[[]]
$if ARITY > 0[[, ]] $for ARG , [[typename P$(ARG)]]>
struct BindState<Runnable, RunType, void($for ARG , [[P$(ARG)]])> : public BindStateBase {
  typedef Runnable RunnableType;

$if ARITY > 0 [[
  typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall;
]] $else [[
  typedef false_type IsWeakCall;
]]

  typedef Invoker<$(ARITY), BindState, RunType> InvokerType;
  typedef typename InvokerType::UnboundRunType UnboundRunType;

$if ARITY > 0 [[

  // Convenience typedefs for bound argument types.

$for ARG [[
  typedef UnwrapTraits<P$(ARG)> Bound$(ARG)UnwrapTraits;

]]  $$ for ARG


]]  $$ if ARITY > 0

$$ The extra [[ ]] is needed to massage spacing. Silly pump.py.
[[  ]]$if ARITY == 0 [[explicit ]]BindState(const Runnable& runnable
$if ARITY > 0 [[, ]] $for ARG , [[const P$(ARG)& p$(ARG)]])
      : runnable_(runnable)[[]]
$if ARITY == 0 [[
 {

]] $else [[
, $for ARG , [[

        p$(ARG)_(p$(ARG))
]] {
    MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_);

]]
  }

  virtual ~BindState() {
$if ARITY > 0 [[
    MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::Release(p1_);
]]
  }

  RunnableType runnable_;

$for ARG [[
  P$(ARG) p$(ARG)_;

]]
};

]] $$ for ARITY

}  // namespace internal
}  // namespace base

#endif  // BASE_BIND_INTERNAL_H_
