OLD | NEW |
---|---|
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef BASE_CALLBACK_H_ | 5 #ifndef BASE_CALLBACK_H_ |
6 #define BASE_CALLBACK_H_ | 6 #define BASE_CALLBACK_H_ |
7 #pragma once | 7 #pragma once |
8 | 8 |
9 #include "base/tuple.h" | 9 #include "base/tuple.h" |
10 #include "base/ref_counted.h" | |
10 #include "base/raw_scoped_refptr_mismatch_checker.h" | 11 #include "base/raw_scoped_refptr_mismatch_checker.h" |
11 | 12 |
12 // Callback -------------------------------------------------------------------- | 13 // Callback -------------------------------------------------------------------- |
13 // | 14 // |
14 // A Callback is like a Task but with unbound parameters. It is basically an | 15 // A Callback is like a Task but with unbound parameters. It is basically an |
15 // object-oriented function pointer. | 16 // object-oriented function pointer. |
16 // | 17 // |
17 // Callbacks are designed to work with Tuples. A set of helper functions and | 18 // Callbacks are designed to work with Tuples. A set of helper functions and |
18 // classes is provided to hide the Tuple details from the consumer. Client | 19 // classes is provided to hide the Tuple details from the consumer. Client |
19 // code will generally work with the CallbackRunner base class, which merely | 20 // code will generally work with the CallbackRunner base class, which merely |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
244 virtual ~CallbackWithReturnValueImpl() {} | 245 virtual ~CallbackWithReturnValueImpl() {} |
245 }; | 246 }; |
246 | 247 |
247 template <class T, typename ReturnValue> | 248 template <class T, typename ReturnValue> |
248 typename CallbackWithReturnValue<ReturnValue>::Type* | 249 typename CallbackWithReturnValue<ReturnValue>::Type* |
249 NewCallbackWithReturnValue(T* object, ReturnValue (T::*method)()) { | 250 NewCallbackWithReturnValue(T* object, ReturnValue (T::*method)()) { |
250 return new CallbackWithReturnValueImpl<T, ReturnValue (T::*)(), ReturnValue>( | 251 return new CallbackWithReturnValueImpl<T, ReturnValue (T::*)(), ReturnValue>( |
251 object, method); | 252 object, method); |
252 } | 253 } |
253 | 254 |
255 // New, super-duper, unified Callback system. This will eventually replace | |
256 // NewRunnableMethod, NewRunnableFunction, CreateFunctor, and CreateCallback | |
257 // systems currently in the Chromium code base. | |
258 // | |
259 // WHAT IS THIS: | |
260 // | |
261 // The templated Callback class is a generalized funciton object. Together | |
262 // with the Prebind() function, they provide a type-safe method for | |
263 // creating a "closure." In programing languages, a closure is a first-class | |
264 // function where all its parameters have been bound. Closures are well suited | |
265 // for passing around a unit of delayed execution. They are used in Chromium | |
266 // code to schedule tasks on different MessageLoops. | |
267 // | |
268 // EXAMPLE USAGE: | |
269 // | |
270 // TODO(ajwong): Add some good examples. | |
271 // | |
272 // | |
273 // WHERE IS THIS DESIGN FROM: | |
274 // | |
275 // The design Callback and Prebind is heavily influenced by C++'s | |
276 // tr1::function/tr1::bind, and by the "Google Callback" system used inside | |
277 // Google. | |
278 // | |
279 // | |
280 // WHY NOT TR1 FUNCTION/BIND? | |
281 // | |
282 // Direct use of tr1::function and tr1::bind was considered, but ultimately | |
283 // rejected because of the number of copy constructors invocations when binding | |
284 // arguments. These copies will no longer be an issue in C++0x; C++0x will | |
285 // support rvalue reference which will solve the copies. However, waiting for | |
286 // C++0x is not an option. | |
287 // | |
288 // Measured with valgrind on gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5), the | |
289 // tr1::bind call itself will invoke a non-trivial copy constructor three times | |
290 // for each bound parameter. Also, each when passing a tr1::function, each | |
291 // bound argument will be copied again. | |
292 namespace base { | |
293 | |
294 // InvokerStorageBase is used to provide an opaque handle that the Callback | |
295 // class can use to represent a function object with bound arguments. It | |
296 // behaves as an existential type that is used by a corresponding | |
297 // PolymorphicInvoke function to perform the function execution. This allows | |
298 // us to shield the Callback class from the types of the bound arguments via | |
299 // "type erasure." | |
300 // | |
301 // TODO(ajwong): Explain the PolymorphicInvoke setup is more understandable | |
302 // terms. | |
303 class InvokerStorageBase : public RefCountedThreadSafe<InvokerStorageBase> { | |
304 protected: | |
305 friend class RefCountedThreadSafe<InvokerStorageBase>; | |
306 virtual ~InvokerStorageBase() {} | |
307 }; | |
308 | |
309 template <typename T> | |
310 struct InvokerStorageHolder { | |
311 explicit InvokerStorageHolder(T* invoker_storage) | |
312 : invoker_storage_(invoker_storage) { | |
313 } | |
314 scoped_refptr<InvokerStorageBase> invoker_storage_; | |
315 }; | |
316 | |
317 // First, forward declare the Callback class template. This informs the | |
318 // compiler that ther template only have 1 type parameter, the function | |
darin (slow to review)
2011/02/01 00:35:56
need to proof read comments. there's a variety of
awong
2011/02/01 01:21:38
Yep...will revisit all comments on the next versio
| |
319 // signature that the Callback is abstracting. | |
320 // | |
321 // After this, create template specializations for 0-5 parameters. Note that | |
322 // even though the template typelist grows, that the specialization still | |
323 // only has one type: the function signature. | |
324 // | |
325 // Also, note that the templated constructor should *not* be explicit. This is | |
326 // to allow the natural assignment syntax from the result of Prebind(). | |
327 template <typename Sig> | |
328 class Callback; | |
329 | |
330 template <typename R> | |
331 class Callback<R(void)> { | |
332 public: | |
333 typedef R(*PolymorphicInvoke)(InvokerStorageBase*); | |
334 | |
335 template <typename T> | |
336 Callback(const InvokerStorageHolder<T>& invoker_holder) | |
337 : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) { | |
338 invoker_storage_.swap( | |
339 const_cast<InvokerStorageHolder<T>&>(invoker_holder).invoker_storage_); | |
340 } | |
341 | |
342 R Run(void) { | |
343 return polymorphic_invoke_(invoker_storage_.get()); | |
344 } | |
345 | |
346 private: | |
347 scoped_refptr<InvokerStorageBase> invoker_storage_; | |
348 PolymorphicInvoke polymorphic_invoke_; | |
349 }; | |
350 | |
351 template <typename R, typename A1> | |
352 class Callback<R(A1)> { | |
353 public: | |
354 typedef R(*PolymorphicInvoke)(InvokerStorageBase*, A1); | |
355 | |
356 template <typename T> | |
357 Callback(const InvokerStorageHolder<T>& invoker_holder) | |
358 : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) { | |
359 invoker_storage_.swap( | |
360 const_cast<InvokerStorageHolder<T>&>(invoker_holder).invoker_storage_); | |
361 } | |
362 | |
363 R Run(A1 a1) { | |
364 return polymorphic_invoke_(invoker_storage_.get(), a1); | |
365 } | |
366 | |
367 private: | |
368 scoped_refptr<InvokerStorageBase> invoker_storage_; | |
369 PolymorphicInvoke polymorphic_invoke_; | |
370 }; | |
371 | |
372 template <typename R, typename A1, typename A2> | |
373 class Callback<R(A1, A2)> { | |
374 public: | |
375 typedef R(*PolymorphicInvoke)(void*, const A1&, const A2&); | |
376 | |
377 template <typename T> | |
378 Callback(const InvokerStorageHolder<T>& invoker_holder) | |
379 : polymorphic_invoke_(&T::FunctionTraits::DoInvoke) { | |
380 invoker_storage_.swap( | |
381 const_cast<InvokerStorageHolder<T>&>(invoker_holder).invoker_storage_); | |
382 } | |
383 | |
384 R Run(const A1& a1, const A2& a2) { | |
385 return polymorphic_invoke_(invoker_storage_.get(), a1, a2); | |
386 } | |
387 | |
388 private: | |
389 scoped_refptr<InvokerStorageBase> invoker_storage_; | |
390 PolymorphicInvoke polymorphic_invoke_; | |
391 }; | |
392 | |
393 | |
394 // Syntactic sugar to make Callbacks<void(void)> easier to read since it will | |
395 // be used in a lot of APIs with delayed execution. | |
396 typedef Callback<void(void)> Closure; | |
397 | |
398 } // namespace base | |
399 | |
254 #endif // BASE_CALLBACK_H | 400 #endif // BASE_CALLBACK_H |
OLD | NEW |