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

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: Illustrates the basic structure of classes. Created 9 years, 11 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
« no previous file with comments | « no previous file | base/prebind.h » ('j') | base/prebind.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 arguments.
willchan no longer on Chromium 2011/01/19 16:57:43 I'm not trying to wordsmith the comments here, jus
awong 2011/01/20 20:27:35 Ooh...good point. Will add a note about it.
284 //
285 // Measured with valgrind on gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5), the
286 // tr1::bind call itself will invoke a non-trivial copy constructor three times
287 // for each bound parameter. Also, each when passing a tr1::function, each
288 // bound argument will be copied again.
289 namespace base {
290
291 // InvokerBase is used to provide an opaque handle that the Callback class can
292 // use to represent a function object with bound arguments. It behaves as an
293 // existential type that is used by a corresponding PolymorphicInvoke function
294 // to perform the function execution. This allows us to shield the Callback
295 // class from the types of the bound arguments via "type erasure."
296 //
297 // TODO(ajwong): Explain the PolymorphicInvoke setup is more understandable
298 // terms.
299 class InvokerBase : public RefCountedThreadSafe<InvokerBase> {
willchan no longer on Chromium 2011/01/19 16:57:43 Just noting that this is RefCountedThreadSafe. Eve
awong 2011/01/20 20:27:35 I think we started talking about it, but never act
300 protected:
301 virtual ~InvokerBase() {}
willchan no longer on Chromium 2011/01/19 16:57:43 Why is this virtual?
awong 2011/01/20 20:27:35 The scope_refptr's static type is scoped_refptr<In
willchan no longer on Chromium 2011/01/21 02:30:12 Yes, I'm wrong. I wrote that comment early on when
302 };
303
304 // First, forward declare the Callback class template. This informs the
305 // compiler that ther template only have 1 type parameter, the function
306 // signature that the Callback is abstracting.
307 //
308 // After this, create template specializations for 0-5 parameters. Note that
309 // even though the template typelist grows, that the specialization still
310 // only has one type: the function signature.
311 template <typename Sig>
312 class Callback;
313
314 template <typename R>
315 class Callback<R(void)> {
316 public:
317 typedef R(*PolymorphicInvoke)(InvokerBase*);
318
319 Callback(InvokerBase* invoker, PolymorphicInvoke* polymorphic_invoke)
320 : invoker_(invoker),
321 polymorphic_invoke_(polymorphic_invoke) {
322 }
323
324 R Run(void) {
325 return polymorphic_invoke_(invoker_.get());
326 }
327
328 private:
329 scoped_refptr<InvokerBase> invoker_;
330 PolymorphicInvoke polymorphic_invoke_;
331 };
332
333 template <typename R, typename A0>
334 class Callback<R(A0)> {
335 public:
336 typedef R(*PolymorphicInvoke)(InvokerBase*, const A0&);
337
338 Callback(InvokerBase* invoker, PolymorphicInvoke* polymorphic_invoke)
339 : invoker_(invoker),
340 polymorphic_invoke_(polymorphic_invoke) {
341 }
342
343 R Run(const A0& a0) {
344 return polymorphic_invoke_(invoker_.get(), a0);
345 }
346
347 private:
348 scoped_refptr<InvokerBase> invoker_;
349 PolymorphicInvoke polymorphic_invoke_;
350 };
351
352 template <typename R, typename A0, typename A1>
353 class Callback<R(A0, A1)> {
354 public:
355 typedef R(*PolymorphicInvoke)(void*, const A0&, const A1&);
356
357 Callback(InvokerBase* invoker, PolymorphicInvoke* polymorphic_invoke)
358 : invoker_(invoker),
359 polymorphic_invoke_(polymorphic_invoke) {
360 }
361
362 R Run(const A0& a0, const A1& a1) {
363 return polymorphic_invoke_(invoker_.get(), a0, a1);
364 }
365
366 private:
367 scoped_refptr<InvokerBase> invoker_;
368 PolymorphicInvoke polymorphic_invoke_;
369 };
370
371
372 // Syntactic sugar to make Callbacks<void(void)> easier to read since it will
373 // be used in a lot of APIs with delayed execution.
374 typename Callback<void(void)> Closure;
375
376 } // namespace base
377
254 #endif // BASE_CALLBACK_H 378 #endif // BASE_CALLBACK_H
OLDNEW
« no previous file with comments | « no previous file | base/prebind.h » ('j') | base/prebind.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698