OLD | NEW |
---|---|
(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 | |
OLD | NEW |