Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(77)

Side by Side Diff: base/uber_callback.h

Issue 6109007: Unified callback system. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/base
Patch Set: pumped up Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // This file was GENERATED by command:
2 // pump.py uber_callback.h.pump
3 // DO NOT EDIT BY HAND!!!
4
5 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
6 // Use of this source code is governed by a BSD-style license that can be
7 // found in the LICENSE file.
8
9 #ifndef BASE_UBER_CALLBACK_H_
10 #define BASE_UBER_CALLBACK_H_
11 #pragma once
12
13 #include "base/ref_counted.h"
14 #include "base/raw_scoped_refptr_mismatch_checker.h"
15
16 // New, super-duper, unified Callback system. This will eventually replace
17 // NewRunnableMethod, NewRunnableFunction, CreateFunctor, and CreateCallback
18 // systems currently in the Chromium code base.
19 //
20 // WHAT IS THIS:
21 //
22 // The templated Callback class is a generalized funciton object. Together
23 // with the Prebind() function, they provide a type-safe method for
24 // creating a "closure." In programing languages, a closure is a first-class
25 // function where all its parameters have been bound. Closures are well suited
26 // for passing around a unit of delayed execution. They are used in Chromium
27 // code to schedule tasks on different MessageLoops.
28 //
29 // EXAMPLE USAGE:
30 //
31 // TODO(ajwong): Add some good examples.
32 //
33 //
34 // WHERE IS THIS DESIGN FROM:
35 //
36 // The design Callback and Prebind is heavily influenced by C++'s
37 // tr1::function/tr1::bind, and by the "Google Callback" system used inside
38 // Google.
39 //
40 //
41 // WHY NOT TR1 FUNCTION/BIND?
42 //
43 // Direct use of tr1::function and tr1::bind was considered, but ultimately
44 // rejected because of the number of copy constructors invocations when binding
45 // arguments. These copies will no longer be an issue in C++0x; C++0x will
46 // support rvalue reference which will solve the copies. However, waiting for
47 // C++0x is not an option.
48 //
49 // Measured with valgrind on gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5), the
50 // tr1::bind call itself will invoke a non-trivial copy constructor three times
51 // for each bound parameter. Also, each when passing a tr1::function, each
52 // bound argument will be copied again.
53
54 namespace base {
55
56 // InvokerStorageBase is used to provide an opaque handle that the Callback
57 // class can use to represent a function object with bound arguments. It
58 // behaves as an existential type that is used by a corresponding
59 // PolymorphicInvoke function to perform the function execution. This allows
60 // us to shield the Callback class from the types of the bound arguments via
61 // "type erasure."
62 //
63 // TODO(ajwong): Explain the PolymorphicInvoke setup is more understandable
64 // terms.
65 class InvokerStorageBase : public RefCountedThreadSafe<InvokerStorageBase> {
66 protected:
67 friend class RefCountedThreadSafe<InvokerStorageBase>;
68 virtual ~InvokerStorageBase() {}
69 };
70
71 template <typename T>
72 struct InvokerStorageHolder {
73 explicit InvokerStorageHolder(T* invoker_storage)
74 : invoker_storage_(invoker_storage) {
75 }
76 scoped_refptr<InvokerStorageBase> invoker_storage_;
77 };
78
79 template <typename T>
80 InvokerStorageHolder<T> MakeInvokerStorageHolder(T* o) {
81 return InvokerStorageHolder<T>(o);
82 }
83
84 // First, forward declare the Callback class template. This informs the
85 // compiler that ther template only have 1 type parameter, the function
86 // signature that the Callback is abstracting.
87 //
88 // After this, create template specializations for 0-5 parameters. Note that
89 // even though the template typelist grows, that the specialization still
90 // only has one type: the function signature.
91 //
92 // Also, note that the templated constructor should *not* be explicit. This is
93 // to allow the natural assignment syntax from the result of Prebind().
94 template <typename Sig>
95 class Callback;
96 template <typename R>
97 class Callback<R(void)> {
98 public:
99 typedef R(*PolymorphicInvoke)(InvokerStorageBase*);
100
101 template <typename T>
102 Callback(const InvokerStorageHolder<T>& invoker_holder)
103 : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
104 invoker_storage_.swap(
105 const_cast<InvokerStorageHolder<T>&>(invoker_holder).invoker_storage_);
akalin 2011/02/01 11:29:27 I don't like this const_cast, although I understan
awong 2011/02/01 23:20:45 I personally prefer the explicitness of the const_
106 }
107
108 R Run(void) {
109 return polymorphic_invoke_(invoker_storage_.get());
110 }
111
112 private:
113 scoped_refptr<InvokerStorageBase> invoker_storage_;
114 PolymorphicInvoke polymorphic_invoke_;
115 };
116
117 template <typename R, typename A1>
118 class Callback<R(A1)> {
119 public:
120 typedef R(*PolymorphicInvoke)(InvokerStorageBase*, A1);
121
122 template <typename T>
123 Callback(const InvokerStorageHolder<T>& invoker_holder)
124 : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
125 invoker_storage_.swap(
126 const_cast<InvokerStorageHolder<T>&>(invoker_holder).invoker_storage_);
127 }
128
129 R Run(A1 a1) {
130 return polymorphic_invoke_(invoker_storage_.get(), a1);
131 }
132
133 private:
134 scoped_refptr<InvokerStorageBase> invoker_storage_;
135 PolymorphicInvoke polymorphic_invoke_;
136 };
137
138 template <typename R, typename A1, typename A2>
139 class Callback<R(A1, A2)> {
140 public:
141 typedef R(*PolymorphicInvoke)(InvokerStorageBase*, A1, A2);
142
143 template <typename T>
144 Callback(const InvokerStorageHolder<T>& invoker_holder)
145 : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
146 invoker_storage_.swap(
147 const_cast<InvokerStorageHolder<T>&>(invoker_holder).invoker_storage_);
148 }
149
150 R Run(A1 a1, A2 a2) {
151 return polymorphic_invoke_(invoker_storage_.get(), a1, a2);
152 }
153
154 private:
155 scoped_refptr<InvokerStorageBase> invoker_storage_;
156 PolymorphicInvoke polymorphic_invoke_;
157 };
158
159 template <typename R, typename A1, typename A2, typename A3>
160 class Callback<R(A1, A2, A3)> {
161 public:
162 typedef R(*PolymorphicInvoke)(InvokerStorageBase*, A1, A2, A3);
163
164 template <typename T>
165 Callback(const InvokerStorageHolder<T>& invoker_holder)
166 : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
167 invoker_storage_.swap(
168 const_cast<InvokerStorageHolder<T>&>(invoker_holder).invoker_storage_);
169 }
170
171 R Run(A1 a1, A2 a2, A3 a3) {
172 return polymorphic_invoke_(invoker_storage_.get(), a1, a2, a3);
173 }
174
175 private:
176 scoped_refptr<InvokerStorageBase> invoker_storage_;
177 PolymorphicInvoke polymorphic_invoke_;
178 };
179
180 template <typename R, typename A1, typename A2, typename A3, typename A4>
181 class Callback<R(A1, A2, A3, A4)> {
182 public:
183 typedef R(*PolymorphicInvoke)(InvokerStorageBase*, A1, A2, A3, A4);
184
185 template <typename T>
186 Callback(const InvokerStorageHolder<T>& invoker_holder)
187 : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
188 invoker_storage_.swap(
189 const_cast<InvokerStorageHolder<T>&>(invoker_holder).invoker_storage_);
190 }
191
192 R Run(A1 a1, A2 a2, A3 a3, A4 a4) {
193 return polymorphic_invoke_(invoker_storage_.get(), a1, a2, a3, a4);
194 }
195
196 private:
197 scoped_refptr<InvokerStorageBase> invoker_storage_;
198 PolymorphicInvoke polymorphic_invoke_;
199 };
200
201 template <typename R, typename A1, typename A2, typename A3, typename A4,
202 typename A5>
203 class Callback<R(A1, A2, A3, A4, A5)> {
204 public:
205 typedef R(*PolymorphicInvoke)(InvokerStorageBase*, A1, A2, A3, A4, A5);
206
207 template <typename T>
208 Callback(const InvokerStorageHolder<T>& invoker_holder)
209 : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
210 invoker_storage_.swap(
211 const_cast<InvokerStorageHolder<T>&>(invoker_holder).invoker_storage_);
212 }
213
214 R Run(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) {
215 return polymorphic_invoke_(invoker_storage_.get(), a1, a2, a3, a4, a5);
216 }
217
218 private:
219 scoped_refptr<InvokerStorageBase> invoker_storage_;
220 PolymorphicInvoke polymorphic_invoke_;
221 };
222
223 template <typename R, typename A1, typename A2, typename A3, typename A4,
224 typename A5, typename A6>
225 class Callback<R(A1, A2, A3, A4, A5, A6)> {
226 public:
227 typedef R(*PolymorphicInvoke)(InvokerStorageBase*, A1, A2, A3, A4, A5, A6);
228
229 template <typename T>
230 Callback(const InvokerStorageHolder<T>& invoker_holder)
231 : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) {
232 invoker_storage_.swap(
233 const_cast<InvokerStorageHolder<T>&>(invoker_holder).invoker_storage_);
234 }
235
236 R Run(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) {
237 return polymorphic_invoke_(invoker_storage_.get(), a1, a2, a3, a4, a5, a6);
238 }
239
240 private:
241 scoped_refptr<InvokerStorageBase> invoker_storage_;
242 PolymorphicInvoke polymorphic_invoke_;
243 };
244
245
246 // Syntactic sugar to make Callbacks<void(void)> easier to read since it will
247 // be used in a lot of APIs with delayed execution.
248 typedef Callback<void(void)> Closure;
249
250 } // namespace base
251
252 #endif // BASE_UBER_CALLBACK_H
OLDNEW
« base/callback_unittest.cc ('K') | « base/prebind.h.pump ('k') | base/uber_callback.h.pump » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698