summaryrefslogtreecommitdiffstats
path: root/chromium/base/bind.h.pump
blob: b321649aea6fbf3f4e5db3153c5983f060a90c22 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
$$ 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
$$

$$
$$ MAX_ARITY controls the number of arguments that Bind() supports.
$$ The amount of code, and more importantly, the number of template types
$$ generated by pump grows at O(MAX_ARITY^2).
$$
$$ We tried going to 11 and found it imposed an extra 10 penalty on windows
$$ cycle times compared to our original baseline of 6.
$$
$$ Currently 7 is chosen as a compromise between supporting a convenient
$$ number of arguments and keeping compile times low.  At 7, we have 115
$$ templates being generated by pump.
$$
$$ Be careful when adjusting this number.  If people find a need to bind
$$ a larger number of arguments, consider refactoring the function to use
$$ a param struct instead of raising the MAX_ARITY.
$$
$$ See http://crbug.com/98542 for more context.
$$
$var MAX_ARITY = 7

// 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_H_
#define BASE_BIND_H_

#include "base/bind_internal.h"
#include "base/callback_internal.h"

// -----------------------------------------------------------------------------
// Usage documentation
// -----------------------------------------------------------------------------
//
// See base/callback.h for documentation.
//
//
// -----------------------------------------------------------------------------
// Implementation notes
// -----------------------------------------------------------------------------
//
// If you're reading the implementation, before proceeding further, you should
// read the top comment of base/bind_internal.h for a definition of common
// terms and concepts.
//
// RETURN TYPES
//
// Though Bind()'s result is meant to be stored in a Callback<> type, it
// cannot actually return the exact type without requiring a large amount
// of extra template specializations. The problem is that in order to
// discern the correct specialization of Callback<>, Bind would need to
// unwrap the function signature to determine the signature's arity, and
// whether or not it is a method.
//
// Each unique combination of (arity, function_type, num_prebound) where
// function_type is one of {function, method, const_method} would require
// one specialization.  We eventually have to do a similar number of
// specializations anyways in the implementation (see the Invoker<>,
// classes).  However, it is avoidable in Bind if we return the result
// via an indirection like we do below.
//
// TODO(ajwong): We might be able to avoid this now, but need to test.
//
// It is possible to move most of the COMPILE_ASSERT asserts into BindState<>,
// but it feels a little nicer to have the asserts here so people do not
// need to crack open bind_internal.h.  On the other hand, it makes Bind()
// harder to read.

namespace base {

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

template <typename Functor[[]]
$if ARITY > 0 [[, ]] $for ARG , [[typename P$(ARG)]]>
base::Callback<
    typename internal::BindState<
        typename internal::FunctorTraits<Functor>::RunnableType,
        typename internal::FunctorTraits<Functor>::RunType,
        void($for ARG , [[typename internal::CallbackParamTraits<P$(ARG)>::StorageType]])>
            ::UnboundRunType>
Bind(Functor functor
$if ARITY > 0 [[, ]] $for ARG , [[const P$(ARG)& p$(ARG)]]) {
  // Typedefs for how to store and run the functor.
  typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType;
  typedef typename internal::FunctorTraits<Functor>::RunType RunType;

  // Use RunnableType::RunType instead of RunType above because our
  // checks should below for bound references need to know what the actual
  // functor is going to interpret the argument as.
  typedef internal::FunctionTraits<typename RunnableType::RunType>
      BoundFunctorTraits;

$if ARITY > 0 [[

  // Do not allow binding a non-const reference parameter. Non-const reference
  // parameters are disallowed by the Google style guide.  Also, binding a
  // non-const reference parameter can make for subtle bugs because the
  // invoked function will receive a reference to the stored copy of the
  // argument and not the original.
  COMPILE_ASSERT(
      !($for ARG || [[
is_non_const_reference<typename BoundFunctorTraits::A$(ARG)Type>::value ]]),
      do_not_bind_functions_with_nonconst_ref);

]]


$for ARG [[


$if ARG == 1 [[
  // For methods, we need to be careful for parameter 1.  We do not require
  // a scoped_refptr because BindState<> itself takes care of AddRef() for
  // methods. We also disallow binding of an array as the method's target
  // object.
  COMPILE_ASSERT(
      internal::HasIsMethodTag<RunnableType>::value ||
          !internal::NeedsScopedRefptrButGetsRawPtr<P$(ARG)>::value,
      p$(ARG)_is_refcounted_type_and_needs_scoped_refptr);
  COMPILE_ASSERT(!internal::HasIsMethodTag<RunnableType>::value ||
                     !is_array<P$(ARG)>::value,
                 first_bound_argument_to_method_cannot_be_array);
]] $else [[
  COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P$(ARG)>::value,
                 p$(ARG)_is_refcounted_type_and_needs_scoped_refptr);
]]  $$ $if ARG

]]  $$ $for ARG

  typedef internal::BindState<RunnableType, RunType, [[]]
void($for ARG , [[typename internal::CallbackParamTraits<P$(ARG)>::StorageType]])> [[]]
BindState;


  return Callback<typename BindState::UnboundRunType>(
      new BindState(internal::MakeRunnable(functor)[[]]
$if ARITY > 0 [[, ]] $for ARG , [[p$(ARG)]]));
}

]]  $$ for ARITY

}  // namespace base

#endif  // BASE_BIND_H_