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

Side by Side Diff: base/bind_helpers.h

Issue 8209001: Callback API Change: Add in an Owned() wrapper to base::Bind(). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fixed Created 9 years, 2 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/bind_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 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 // This defines a set of argument wrappers and related factory methods that 5 // This defines a set of argument wrappers and related factory methods that
6 // can be used specify the refcounting and reference semantics of arguments 6 // can be used specify the refcounting and reference semantics of arguments
7 // that are bound by the Bind() function in base/bind.h. 7 // that are bound by the Bind() function in base/bind.h.
8 // 8 //
9 // The public functions are base::Unretained(), base::ConstRef(), and 9 // The public functions are base::Unretained(), base::Owned(),
10 // base::IgnoreReturn(). 10 // base::ConstRef(), and base::IgnoreReturn().
11 // 11 //
12 // Unretained() allows Bind() to bind a non-refcounted class. 12 // Unretained() allows Bind() to bind a non-refcounted class, and to disable
13 // refcounting on arguments that are refcounted objects.
14 // Owned() transfers ownership of an object to the Callback resulting from
15 // bind; the object will be deleted when the Callback is deleted.
13 // ConstRef() allows binding a constant reference to an argument rather 16 // ConstRef() allows binding a constant reference to an argument rather
14 // than a copy. 17 // than a copy.
15 // IgnoreReturn() is used to adapt a 0-argument Callback with a return type to 18 // IgnoreReturn() is used to adapt a 0-argument Callback with a return type to
16 // a Closure. This is useful if you need to PostTask with a function that has 19 // a Closure. This is useful if you need to PostTask with a function that has
17 // a return value that you don't care about. 20 // a return value that you don't care about.
18 // 21 //
19 // 22 //
20 // EXAMPLE OF Unretained(): 23 // EXAMPLE OF Unretained():
21 // 24 //
22 // class Foo { 25 // class Foo {
23 // public: 26 // public:
24 // void func() { cout << "Foo:f" << endl; } 27 // void func() { cout << "Foo:f" << endl; }
25 // }; 28 // };
26 // 29 //
27 // // In some function somewhere. 30 // // In some function somewhere.
28 // Foo foo; 31 // Foo foo;
29 // Callback<void(void)> foo_callback = 32 // Closure foo_callback =
30 // Bind(&Foo::func, Unretained(&foo)); 33 // Bind(&Foo::func, Unretained(&foo));
31 // foo_callback.Run(); // Prints "Foo:f". 34 // foo_callback.Run(); // Prints "Foo:f".
32 // 35 //
33 // Without the Unretained() wrapper on |&foo|, the above call would fail 36 // Without the Unretained() wrapper on |&foo|, the above call would fail
34 // to compile because Foo does not support the AddRef() and Release() methods. 37 // to compile because Foo does not support the AddRef() and Release() methods.
35 // 38 //
36 // 39 //
40 // EXAMPLE OF Owned():
41 //
42 // void foo(int* arg) { cout << *arg << endl }
43 //
44 // int* pn = new int(1);
45 // Closure foo_callback = Bind(&foo, Owned(pn));
46 //
47 // foo_callback.Run(); // Prints "1"
48 // foo_callback.Run(); // Prints "1"
49 // *n = 2;
50 // foo_callback.Run(); // Prints "2"
51 //
52 // foo_callback.Reset(); // |pn| is deleted. Also will happen when
53 // // |foo_callback| goes out of scope.
54 //
55 // Without Owned(), someone would have to know to delete |pn| when the last
56 // reference to the Callback is deleted.
57 //
58 //
37 // EXAMPLE OF ConstRef(): 59 // EXAMPLE OF ConstRef():
60 //
38 // void foo(int arg) { cout << arg << endl } 61 // void foo(int arg) { cout << arg << endl }
39 // 62 //
40 // int n = 1; 63 // int n = 1;
41 // Callback<void(void)> no_ref = Bind(&foo, n); 64 // Closure no_ref = Bind(&foo, n);
42 // Callback<void(void)> has_ref = Bind(&foo, ConstRef(n)); 65 // Closure has_ref = Bind(&foo, ConstRef(n));
43 // 66 //
44 // no_ref.Run(); // Prints "1" 67 // no_ref.Run(); // Prints "1"
45 // has_ref.Run(); // Prints "1" 68 // has_ref.Run(); // Prints "1"
46 // 69 //
47 // n = 2; 70 // n = 2;
48 // no_ref.Run(); // Prints "1" 71 // no_ref.Run(); // Prints "1"
49 // has_ref.Run(); // Prints "2" 72 // has_ref.Run(); // Prints "2"
50 // 73 //
51 // Note that because ConstRef() takes a reference on |n|, |n| must outlive all 74 // Note that because ConstRef() takes a reference on |n|, |n| must outlive all
52 // its bound callbacks. 75 // its bound callbacks.
53 // 76 //
54 // 77 //
55 // EXAMPLE OF IgnoreReturn(): 78 // EXAMPLE OF IgnoreReturn():
79 //
56 // int DoSomething(int arg) { cout << arg << endl; } 80 // int DoSomething(int arg) { cout << arg << endl; }
57 // Callback<int(void)> cb = Bind(&DoSomething, 1); 81 // Callback<int(void)> cb = Bind(&DoSomething, 1);
58 // Closure c = IgnoreReturn(cb); // Prints "1" 82 // Closure c = IgnoreReturn(cb); // Prints "1"
59 // or 83 // or
60 // ml->PostTask(FROM_HERE, IgnoreReturn(cb)); // Prints "1" on |ml| 84 // ml->PostTask(FROM_HERE, IgnoreReturn(cb)); // Prints "1" on |ml|
61 85
62 #ifndef BASE_BIND_HELPERS_H_ 86 #ifndef BASE_BIND_HELPERS_H_
63 #define BASE_BIND_HELPERS_H_ 87 #define BASE_BIND_HELPERS_H_
64 #pragma once 88 #pragma once
65 89
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 216
193 template <typename T> 217 template <typename T>
194 struct UnsafeBindtoRefCountedArg<T*> 218 struct UnsafeBindtoRefCountedArg<T*>
195 : UnsafeBindtoRefCountedArgHelper<is_class<T>::value, T> { 219 : UnsafeBindtoRefCountedArgHelper<is_class<T>::value, T> {
196 }; 220 };
197 221
198 222
199 template <typename T> 223 template <typename T>
200 class UnretainedWrapper { 224 class UnretainedWrapper {
201 public: 225 public:
202 explicit UnretainedWrapper(T* o) : obj_(o) {} 226 explicit UnretainedWrapper(T* o) : ptr_(o) {}
203 T* get() { return obj_; } 227 T* get() const { return ptr_; }
204 private: 228 private:
205 T* obj_; 229 T* ptr_;
206 }; 230 };
207 231
208 template <typename T> 232 template <typename T>
209 class ConstRefWrapper { 233 class ConstRefWrapper {
210 public: 234 public:
211 explicit ConstRefWrapper(const T& o) : ptr_(&o) {} 235 explicit ConstRefWrapper(const T& o) : ptr_(&o) {}
212 const T& get() { return *ptr_; } 236 const T& get() const { return *ptr_; }
213 private: 237 private:
214 const T* ptr_; 238 const T* ptr_;
215 }; 239 };
216 240
241 // An alternate implementation is to avoid the destructive copy, and instead
242 // specialize ParamTraits<> for OwnedWrapper<> to change the StorageType to
243 // a class that is essentially a scoped_ptr<>.
244 //
245 // The current implementation has the benefit though of leaving ParamTraits<>
246 // fully in callback_internal.h as well as avoiding type conversions during
247 // storage.
248 template <typename T>
249 class OwnedWrapper {
250 public:
251 explicit OwnedWrapper(T* o) : ptr_(o) {}
252 ~OwnedWrapper() { delete ptr_; }
253 T* get() const { return ptr_; }
254 OwnedWrapper(const OwnedWrapper& other) {
255 ptr_ = other.ptr_;
256 other.ptr_ = NULL;
257 }
258
259 private:
260 mutable T* ptr_;
261 };
262
217 263
218 // Unwrap the stored parameters for the wrappers above. 264 // Unwrap the stored parameters for the wrappers above.
219 template <typename T> 265 template <typename T>
220 T Unwrap(T o) { return o; } 266 T Unwrap(T o) { return o; }
221 267
222 template <typename T> 268 template <typename T>
223 T* Unwrap(UnretainedWrapper<T> unretained) { return unretained.get(); } 269 T* Unwrap(UnretainedWrapper<T> unretained) { return unretained.get(); }
224 270
225 template <typename T> 271 template <typename T>
226 const T& Unwrap(ConstRefWrapper<T> const_ref) { 272 const T& Unwrap(ConstRefWrapper<T> const_ref) {
227 return const_ref.get(); 273 return const_ref.get();
228 } 274 }
229 275
230 template <typename T> 276 template <typename T>
231 T* Unwrap(const scoped_refptr<T>& o) { return o.get(); } 277 T* Unwrap(const scoped_refptr<T>& o) { return o.get(); }
232 278
233 template <typename T> 279 template <typename T>
234 const WeakPtr<T>& Unwrap(const WeakPtr<T>& o) { return o; } 280 const WeakPtr<T>& Unwrap(const WeakPtr<T>& o) { return o; }
235 281
282 template <typename T>
283 T* Unwrap(const OwnedWrapper<T>& o) {
284 return o.get();
285 }
286
236 // Utility for handling different refcounting semantics in the Bind() 287 // Utility for handling different refcounting semantics in the Bind()
237 // function. 288 // function.
238 template <typename IsMethod, typename T> 289 template <typename IsMethod, typename T>
239 struct MaybeRefcount; 290 struct MaybeRefcount;
240 291
241 template <typename T> 292 template <typename T>
242 struct MaybeRefcount<base::false_type, T> { 293 struct MaybeRefcount<base::false_type, T> {
243 static void AddRef(const T&) {} 294 static void AddRef(const T&) {}
244 static void Release(const T&) {} 295 static void Release(const T&) {}
245 }; 296 };
246 297
247 template <typename T, size_t n> 298 template <typename T, size_t n>
248 struct MaybeRefcount<base::false_type, T[n]> { 299 struct MaybeRefcount<base::false_type, T[n]> {
249 static void AddRef(const T*) {} 300 static void AddRef(const T*) {}
250 static void Release(const T*) {} 301 static void Release(const T*) {}
251 }; 302 };
252 303
253 template <typename T> 304 template <typename T>
305 struct MaybeRefcount<base::true_type, T*> {
306 static void AddRef(T* o) { o->AddRef(); }
307 static void Release(T* o) { o->Release(); }
308 };
309
310 template <typename T>
254 struct MaybeRefcount<base::true_type, UnretainedWrapper<T> > { 311 struct MaybeRefcount<base::true_type, UnretainedWrapper<T> > {
255 static void AddRef(const UnretainedWrapper<T>&) {} 312 static void AddRef(const UnretainedWrapper<T>&) {}
256 static void Release(const UnretainedWrapper<T>&) {} 313 static void Release(const UnretainedWrapper<T>&) {}
257 }; 314 };
258 315
259 template <typename T> 316 template <typename T>
260 struct MaybeRefcount<base::true_type, T*> { 317 struct MaybeRefcount<base::true_type, OwnedWrapper<T> > {
261 static void AddRef(T* o) { o->AddRef(); } 318 static void AddRef(const OwnedWrapper<T>&) {}
262 static void Release(T* o) { o->Release(); } 319 static void Release(const OwnedWrapper<T>&) {}
263 }; 320 };
264 321
265 // No need to additionally AddRef() and Release() since we are storing a 322 // No need to additionally AddRef() and Release() since we are storing a
266 // scoped_refptr<> inside the storage object already. 323 // scoped_refptr<> inside the storage object already.
267 template <typename T> 324 template <typename T>
268 struct MaybeRefcount<base::true_type, scoped_refptr<T> > { 325 struct MaybeRefcount<base::true_type, scoped_refptr<T> > {
269 static void AddRef(const scoped_refptr<T>& o) {} 326 static void AddRef(const scoped_refptr<T>& o) {}
270 static void Release(const scoped_refptr<T>& o) {} 327 static void Release(const scoped_refptr<T>& o) {}
271 }; 328 };
272 329
(...skipping 19 matching lines...) Expand all
292 template <typename T> 349 template <typename T>
293 inline internal::UnretainedWrapper<T> Unretained(T* o) { 350 inline internal::UnretainedWrapper<T> Unretained(T* o) {
294 return internal::UnretainedWrapper<T>(o); 351 return internal::UnretainedWrapper<T>(o);
295 } 352 }
296 353
297 template <typename T> 354 template <typename T>
298 inline internal::ConstRefWrapper<T> ConstRef(const T& o) { 355 inline internal::ConstRefWrapper<T> ConstRef(const T& o) {
299 return internal::ConstRefWrapper<T>(o); 356 return internal::ConstRefWrapper<T>(o);
300 } 357 }
301 358
359 template <typename T>
360 inline internal::OwnedWrapper<T> Owned(T* o) {
361 return internal::OwnedWrapper<T>(o);
362 }
363
302 template <typename R> 364 template <typename R>
303 Closure IgnoreReturn(Callback<R(void)> callback) { 365 Closure IgnoreReturn(Callback<R(void)> callback) {
304 return Bind(&internal::VoidReturnAdapter<R>, callback); 366 return Bind(&internal::VoidReturnAdapter<R>, callback);
305 } 367 }
306 368
307 } // namespace base 369 } // namespace base
308 370
309 #endif // BASE_BIND_HELPERS_H_ 371 #endif // BASE_BIND_HELPERS_H_
OLDNEW
« no previous file with comments | « no previous file | base/bind_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698