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

Side by Side Diff: base/callback.h

Issue 6109007: Unified callback system. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/base
Patch Set: Ready for another structural review. (not optimized) 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
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
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
OLDNEW
« no previous file with comments | « base/base.gypi ('k') | base/callback_unittest.cc » ('j') | base/callback_unittest.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698