summaryrefslogtreecommitdiffstats
path: root/base/callback.h
blob: fbd81d82bed296b8844625f3af1aabcf1dab6bab (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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
// This file was GENERATED by command:
//     pump.py callback.h.pump
// DO NOT EDIT BY HAND!!!



// 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_CALLBACK_H_
#define BASE_CALLBACK_H_
#pragma once

#include "base/callback_internal.h"

// New, super-duper, unified Callback system.  This will eventually replace
// NewRunnableMethod, NewRunnableFunction, CreateFunctor, and CreateCallback
// systems currently in the Chromium code base.
//
// WHAT IS THIS:
//
// The templated Callback class is a generalized function object. Together
// with the Bind() function in bind.h, they provide a type-safe method for
// performing currying of arguments, and creating a "closure."
//
// In programing languages, a closure is a first-class function where all its
// parameters have been bound (usually via currying).  Closures are well
// suited for representing, and passing around a unit of delayed execution.
// They are used in Chromium code to schedule tasks on different MessageLoops.
//
//
// MEMORY MANAGEMENT AND PASSING
//
// The Callback objects themselves should be passed by const-reference, and
// stored by copy. They internally store their state via a refcounted class
// and thus do not need to be deleted.
//
// The reason to pass via a const-reference is to avoid unnecessary
// AddRef/Release pairs to the internal state.
//
//
// EXAMPLE USAGE:
//
// /* Binding a normal function. */
// int Return5() { return 5; }
// base::Callback<int(void)> func_cb = base::Bind(&Return5);
// LOG(INFO) << func_cb.Run();  // Prints 5.
//
// void PrintHi() { LOG(INFO) << "hi."; }
// base::Closure void_func_cb = base::Bind(&PrintHi);
// void_func_cb.Run();  // Prints: hi.
//
// /* Binding a class method. */
// class Ref : public RefCountedThreadSafe<Ref> {
//  public:
//   int Foo() { return 3; }
//   void PrintBye() { LOG(INFO) << "bye."; }
// };
// scoped_refptr<Ref> ref = new Ref();
// base::Callback<int(void)> ref_cb = base::Bind(&Ref::Foo, ref.get());
// LOG(INFO) << ref_cb.Run();  // Prints out 3.
//
// base::Closure void_ref_cb = base::Bind(&Ref::PrintBye, ref.get());
// void_ref_cb.Run();  // Prints: bye.
//
// /* Binding a class method in a non-refcounted class.
//  *
//  * WARNING: You must be sure the referee outlives the callback!
//  *          This is particularly important if you post a closure to a
//  *          MessageLoop because then it becomes hard to know what the
//  *          lifetime of the referee needs to be.
//  */
// class NoRef {
//  public:
//   int Foo() { return 4; }
//   void PrintWhy() { LOG(INFO) << "why???"; }
// };
// NoRef no_ref;
// base::Callback<int(void)> base::no_ref_cb =
//     base::Bind(&NoRef::Foo, base::Unretained(&no_ref));
// LOG(INFO) << ref_cb.Run();  // Prints out 4.
//
// base::Closure void_no_ref_cb =
//     base::Bind(&NoRef::PrintWhy, base::Unretained(no_ref));
// void_no_ref_cb.Run();  // Prints: why???
//
// /* Binding a reference. */
// int Identity(int n) { return n; }
// int value = 1;
// base::Callback<int(void)> bound_copy_cb = base::Bind(&Identity, value);
// base::Callback<int(void)> bound_ref_cb =
//     base::Bind(&Identity, base::ConstRef(value));
// LOG(INFO) << bound_copy_cb.Run();  // Prints 1.
// LOG(INFO) << bound_ref_cb.Run();  // Prints 1.
// value = 2;
// LOG(INFO) << bound_copy_cb.Run();  // Prints 1.
// LOG(INFO) << bound_ref_cb.Run();  // Prints 2.
//
//
// WHERE IS THIS DESIGN FROM:
//
// The design Callback and Bind is heavily influenced by C++'s
// tr1::function/tr1::bind, and by the "Google Callback" system used inside
// Google.
//
//
// HOW THE IMPLEMENTATION WORKS:
//
// There are three main components to the system:
//   1) The Callback classes.
//   2) The Bind() functions.
//   3) The arguments wrappers (eg., Unretained() and ConstRef()).
//
// The Callback classes represent a generic function pointer. Internally,
// it stores a refcounted piece of state that represents the target function
// and all its bound parameters.  Each Callback specialization has a templated
// constructor that takes an InvokerStorageHolder<> object.  In the context of
// the constructor, the static type of this InvokerStorageHolder<> object
// uniquely identifies the function it is representing, all its bound
// parameters, and a DoInvoke() that is capable of invoking the target.
//
// Callback's constructor is takes the InvokerStorageHolder<> that has the
// full static type and erases the target function type, and the bound
// parameters.  It does this by storing a pointer to the specific DoInvoke()
// function, and upcasting the state of InvokerStorageHolder<> to a
// InvokerStorageBase. This is safe as long as this InvokerStorageBase pointer
// is only used with the stored DoInvoke() pointer.
//
// To create InvokerStorageHolder<> objects, we use the Bind() functions.
// These functions, along with a set of internal templates, are reponsible for
//
//  - Unwrapping the function signature into return type, and parameters
//  - Determining the number of parameters that are bound
//  - Creating the storage for the bound parameters
//  - Performing compile-time asserts to avoid error-prone behavior
//  - Returning an InvokerStorageHolder<> with an DoInvoke() that has an arity
//    matching the number of unbound parameters, and knows the correct
//    refcounting semantics for the target object if we are binding a class
//    method.
//
// The Bind functions do the above using type-inference, and template
// specializations.
//
// By default Bind() will store copies of all bound parameters, and attempt
// to refcount a target object if the function being bound is a class method.
//
// To change this behavior, we introduce a set of argument wrappers
// (eg. Unretained(), and ConstRef()).  These are simple container templates
// that are passed by value, and wrap a pointer to argument.  See the
// file-level comment in base/bind_helpers.h for more info.
//
// These types are passed to the Unwrap() functions, and the MaybeRefcount()
// functions respectively to modify the behavior of Bind().  The Unwrap()
// and MaybeRefcount() functions change behavior by doing partial
// specialization based on whether or not a parameter is a wrapper type.
//
// ConstRef() is similar to tr1::cref.  Unretained() is specific to Chromium.
//
//
// WHY NOT TR1 FUNCTION/BIND?
//
// Direct use of tr1::function and tr1::bind was considered, but ultimately
// rejected because of the number of copy constructors invocations involved
// in the binding of arguments during construction, and the forwarding of
// arguments during invocation.  These copies will no longer be an issue in
// C++0x because C++0x will support rvalue reference allowing for the compiler
// to avoid these copies.  However, waiting for C++0x is not an option.
//
// Measured with valgrind on gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5), the
// tr1::bind call itself will invoke a non-trivial copy constructor three times
// for each bound parameter.  Also, each when passing a tr1::function, each
// bound argument will be copied again.
//
// In addition to the copies taken at binding and invocation, copying a
// tr1::function causes a copy to be made of all the bound parameters and
// state.
//
// Furthermore, in Chromium, it is desirable for the Callback to take a
// reference on a target object when representing a class method call.  This
// is not supported by tr1.
//
// Lastly, tr1::function and tr1::bind has a more general and flexible API.
// This includes things like argument reordering by use of
// tr1::bind::placeholder, support for non-const reference parameters, and some
// limited amount of subtyping of the tr1::function object (eg.,
// tr1::function<int(int)> is convertible to tr1::function<void(int)>).
//
// These are not features that are required in Chromium. Some of them, such as
// allowing for reference parameters, and subtyping of functions, may actually
// become a source of errors. Removing support for these features actually
// allows for a simpler implementation, and a terser Currying API.
//
//
// WHY NOT GOOGLE CALLBACKS?
//
// The Google callback system also does not support refcounting.  Furthermore,
// its implementation has a number of strange edge cases with respect to type
// conversion of its arguments.  In particular, the argument's constness must
// at times match exactly the function signature, or the type-inference might
// break.  Given the above, writing a custom solution was easier.
//
//
// MISSING FUNCTIONALITY
//  - Invoking the return of Bind.  Bind(&foo).Run() does not work;
//  - Binding arrays to functions that take a non-const pointer.
//    Example:
//      void Foo(const char* ptr);
//      void Bar(char* ptr);
//      Bind(&Foo, "test");
//      Bind(&Bar, "test");  // This fails because ptr is not const.

namespace base {

// First, we forward declare the Callback class template. This informs the
// compiler that the template only has 1 type parameter which is the function
// signature that the Callback is representing.
//
// After this, create template specializations for 0-6 parameters. Note that
// even though the template typelist grows, the specialization still
// only has one type: the function signature.
template <typename Sig>
class Callback;

template <typename R>
class Callback<R(void)> : public internal::CallbackBase {
 public:
  typedef R(*PolymorphicInvoke)(
      internal::InvokerStorageBase*);

  Callback() : CallbackBase(NULL, NULL) { }

  // We pass InvokerStorageHolder by const ref to avoid incurring an
  // unnecessary AddRef/Unref pair even though we will modify the object.
  // We cannot use a normal reference because the compiler will warn
  // since this is often used on a return value, which is a temporary.
  //
  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
  // return the exact Callback<> type.  See base/bind.h for details.
  template <typename T>
  Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
      : CallbackBase(
          reinterpret_cast<InvokeFuncStorage>(&T::Invoker::DoInvoke),
          &invoker_holder.invoker_storage_) {
  }

  R Run() const {
    PolymorphicInvoke f =
        reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);

    return f(invoker_storage_.get());
  }
};

template <typename R, typename A1>
class Callback<R(A1)> : public internal::CallbackBase {
 public:
  typedef R(*PolymorphicInvoke)(
      internal::InvokerStorageBase*,
          typename internal::ParamTraits<A1>::ForwardType);

  Callback() : CallbackBase(NULL, NULL) { }

  // We pass InvokerStorageHolder by const ref to avoid incurring an
  // unnecessary AddRef/Unref pair even though we will modify the object.
  // We cannot use a normal reference because the compiler will warn
  // since this is often used on a return value, which is a temporary.
  //
  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
  // return the exact Callback<> type.  See base/bind.h for details.
  template <typename T>
  Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
      : CallbackBase(
          reinterpret_cast<InvokeFuncStorage>(&T::Invoker::DoInvoke),
          &invoker_holder.invoker_storage_) {
  }

  R Run(typename internal::ParamTraits<A1>::ForwardType a1) const {
    PolymorphicInvoke f =
        reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);

    return f(invoker_storage_.get(), a1);
  }
};

template <typename R, typename A1, typename A2>
class Callback<R(A1, A2)> : public internal::CallbackBase {
 public:
  typedef R(*PolymorphicInvoke)(
      internal::InvokerStorageBase*,
          typename internal::ParamTraits<A1>::ForwardType,
          typename internal::ParamTraits<A2>::ForwardType);

  Callback() : CallbackBase(NULL, NULL) { }

  // We pass InvokerStorageHolder by const ref to avoid incurring an
  // unnecessary AddRef/Unref pair even though we will modify the object.
  // We cannot use a normal reference because the compiler will warn
  // since this is often used on a return value, which is a temporary.
  //
  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
  // return the exact Callback<> type.  See base/bind.h for details.
  template <typename T>
  Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
      : CallbackBase(
          reinterpret_cast<InvokeFuncStorage>(&T::Invoker::DoInvoke),
          &invoker_holder.invoker_storage_) {
  }

  R Run(typename internal::ParamTraits<A1>::ForwardType a1,
        typename internal::ParamTraits<A2>::ForwardType a2) const {
    PolymorphicInvoke f =
        reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);

    return f(invoker_storage_.get(), a1,
             a2);
  }
};

template <typename R, typename A1, typename A2, typename A3>
class Callback<R(A1, A2, A3)> : public internal::CallbackBase {
 public:
  typedef R(*PolymorphicInvoke)(
      internal::InvokerStorageBase*,
          typename internal::ParamTraits<A1>::ForwardType,
          typename internal::ParamTraits<A2>::ForwardType,
          typename internal::ParamTraits<A3>::ForwardType);

  Callback() : CallbackBase(NULL, NULL) { }

  // We pass InvokerStorageHolder by const ref to avoid incurring an
  // unnecessary AddRef/Unref pair even though we will modify the object.
  // We cannot use a normal reference because the compiler will warn
  // since this is often used on a return value, which is a temporary.
  //
  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
  // return the exact Callback<> type.  See base/bind.h for details.
  template <typename T>
  Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
      : CallbackBase(
          reinterpret_cast<InvokeFuncStorage>(&T::Invoker::DoInvoke),
          &invoker_holder.invoker_storage_) {
  }

  R Run(typename internal::ParamTraits<A1>::ForwardType a1,
        typename internal::ParamTraits<A2>::ForwardType a2,
        typename internal::ParamTraits<A3>::ForwardType a3) const {
    PolymorphicInvoke f =
        reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);

    return f(invoker_storage_.get(), a1,
             a2,
             a3);
  }
};

template <typename R, typename A1, typename A2, typename A3, typename A4>
class Callback<R(A1, A2, A3, A4)> : public internal::CallbackBase {
 public:
  typedef R(*PolymorphicInvoke)(
      internal::InvokerStorageBase*,
          typename internal::ParamTraits<A1>::ForwardType,
          typename internal::ParamTraits<A2>::ForwardType,
          typename internal::ParamTraits<A3>::ForwardType,
          typename internal::ParamTraits<A4>::ForwardType);

  Callback() : CallbackBase(NULL, NULL) { }

  // We pass InvokerStorageHolder by const ref to avoid incurring an
  // unnecessary AddRef/Unref pair even though we will modify the object.
  // We cannot use a normal reference because the compiler will warn
  // since this is often used on a return value, which is a temporary.
  //
  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
  // return the exact Callback<> type.  See base/bind.h for details.
  template <typename T>
  Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
      : CallbackBase(
          reinterpret_cast<InvokeFuncStorage>(&T::Invoker::DoInvoke),
          &invoker_holder.invoker_storage_) {
  }

  R Run(typename internal::ParamTraits<A1>::ForwardType a1,
        typename internal::ParamTraits<A2>::ForwardType a2,
        typename internal::ParamTraits<A3>::ForwardType a3,
        typename internal::ParamTraits<A4>::ForwardType a4) const {
    PolymorphicInvoke f =
        reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);

    return f(invoker_storage_.get(), a1,
             a2,
             a3,
             a4);
  }
};

template <typename R, typename A1, typename A2, typename A3, typename A4,
    typename A5>
class Callback<R(A1, A2, A3, A4, A5)> : public internal::CallbackBase {
 public:
  typedef R(*PolymorphicInvoke)(
      internal::InvokerStorageBase*,
          typename internal::ParamTraits<A1>::ForwardType,
          typename internal::ParamTraits<A2>::ForwardType,
          typename internal::ParamTraits<A3>::ForwardType,
          typename internal::ParamTraits<A4>::ForwardType,
          typename internal::ParamTraits<A5>::ForwardType);

  Callback() : CallbackBase(NULL, NULL) { }

  // We pass InvokerStorageHolder by const ref to avoid incurring an
  // unnecessary AddRef/Unref pair even though we will modify the object.
  // We cannot use a normal reference because the compiler will warn
  // since this is often used on a return value, which is a temporary.
  //
  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
  // return the exact Callback<> type.  See base/bind.h for details.
  template <typename T>
  Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
      : CallbackBase(
          reinterpret_cast<InvokeFuncStorage>(&T::Invoker::DoInvoke),
          &invoker_holder.invoker_storage_) {
  }

  R Run(typename internal::ParamTraits<A1>::ForwardType a1,
        typename internal::ParamTraits<A2>::ForwardType a2,
        typename internal::ParamTraits<A3>::ForwardType a3,
        typename internal::ParamTraits<A4>::ForwardType a4,
        typename internal::ParamTraits<A5>::ForwardType a5) const {
    PolymorphicInvoke f =
        reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);

    return f(invoker_storage_.get(), a1,
             a2,
             a3,
             a4,
             a5);
  }
};

template <typename R, typename A1, typename A2, typename A3, typename A4,
    typename A5, typename A6>
class Callback<R(A1, A2, A3, A4, A5, A6)> : public internal::CallbackBase {
 public:
  typedef R(*PolymorphicInvoke)(
      internal::InvokerStorageBase*,
          typename internal::ParamTraits<A1>::ForwardType,
          typename internal::ParamTraits<A2>::ForwardType,
          typename internal::ParamTraits<A3>::ForwardType,
          typename internal::ParamTraits<A4>::ForwardType,
          typename internal::ParamTraits<A5>::ForwardType,
          typename internal::ParamTraits<A6>::ForwardType);

  Callback() : CallbackBase(NULL, NULL) { }

  // We pass InvokerStorageHolder by const ref to avoid incurring an
  // unnecessary AddRef/Unref pair even though we will modify the object.
  // We cannot use a normal reference because the compiler will warn
  // since this is often used on a return value, which is a temporary.
  //
  // Note that this constructor CANNOT be explicit, and that Bind() CANNOT
  // return the exact Callback<> type.  See base/bind.h for details.
  template <typename T>
  Callback(const internal::InvokerStorageHolder<T>& invoker_holder)
      : CallbackBase(
          reinterpret_cast<InvokeFuncStorage>(&T::Invoker::DoInvoke),
          &invoker_holder.invoker_storage_) {
  }

  R Run(typename internal::ParamTraits<A1>::ForwardType a1,
        typename internal::ParamTraits<A2>::ForwardType a2,
        typename internal::ParamTraits<A3>::ForwardType a3,
        typename internal::ParamTraits<A4>::ForwardType a4,
        typename internal::ParamTraits<A5>::ForwardType a5,
        typename internal::ParamTraits<A6>::ForwardType a6) const {
    PolymorphicInvoke f =
        reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_);

    return f(invoker_storage_.get(), a1,
             a2,
             a3,
             a4,
             a5,
             a6);
  }
};


// Syntactic sugar to make Callbacks<void(void)> easier to declare since it
// will be used in a lot of APIs with delayed execution.
typedef Callback<void(void)> Closure;

}  // namespace base

#endif  // BASE_CALLBACK_H