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

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: fix comment. 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():
darin (slow to review) 2011/10/14 21:53:07 nit: new line below this line as you did for Unret
awong 2011/10/15 00:19:16 Done. Also fixed ConstRef and IgnoreReturn.
41 // void foo(int* arg) { cout << *arg << endl }
42 //
43 // int* pn = new int(1);
44 // Closure foo_callback = Bind(&foo, Owned(pn));
45 //
46 // foo_callback.Run(); // Prints "1"
47 // foo_callback.Run(); // Prints "1"
48 // *n = 2;
49 // foo_callback.Run(); // Prints "2"
50 //
51 // foo_callback.Reset(); // |pn| is deleted. Also will happen when
52 // // |foo_callback| goes out of scope.
53 //
54 // Without Owned(), someone would have to know to delete |pn| when the last
55 // reference to the Callback is deleted.
56 //
57 //
37 // EXAMPLE OF ConstRef(): 58 // EXAMPLE OF ConstRef():
38 // void foo(int arg) { cout << arg << endl } 59 // void foo(int arg) { cout << arg << endl }
39 // 60 //
40 // int n = 1; 61 // int n = 1;
41 // Callback<void(void)> no_ref = Bind(&foo, n); 62 // Closure no_ref = Bind(&foo, n);
42 // Callback<void(void)> has_ref = Bind(&foo, ConstRef(n)); 63 // Closure has_ref = Bind(&foo, ConstRef(n));
43 // 64 //
44 // no_ref.Run(); // Prints "1" 65 // no_ref.Run(); // Prints "1"
45 // has_ref.Run(); // Prints "1" 66 // has_ref.Run(); // Prints "1"
46 // 67 //
47 // n = 2; 68 // n = 2;
48 // no_ref.Run(); // Prints "1" 69 // no_ref.Run(); // Prints "1"
49 // has_ref.Run(); // Prints "2" 70 // has_ref.Run(); // Prints "2"
50 // 71 //
51 // Note that because ConstRef() takes a reference on |n|, |n| must outlive all 72 // Note that because ConstRef() takes a reference on |n|, |n| must outlive all
52 // its bound callbacks. 73 // its bound callbacks.
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 213
193 template <typename T> 214 template <typename T>
194 struct UnsafeBindtoRefCountedArg<T*> 215 struct UnsafeBindtoRefCountedArg<T*>
195 : UnsafeBindtoRefCountedArgHelper<is_class<T>::value, T> { 216 : UnsafeBindtoRefCountedArgHelper<is_class<T>::value, T> {
196 }; 217 };
197 218
198 219
199 template <typename T> 220 template <typename T>
200 class UnretainedWrapper { 221 class UnretainedWrapper {
201 public: 222 public:
202 explicit UnretainedWrapper(T* o) : obj_(o) {} 223 explicit UnretainedWrapper(T* o) : ptr_(o) {}
203 T* get() { return obj_; } 224 T* get() const { return ptr_; }
204 private: 225 private:
205 T* obj_; 226 T* ptr_;
206 }; 227 };
207 228
208 template <typename T> 229 template <typename T>
209 class ConstRefWrapper { 230 class ConstRefWrapper {
210 public: 231 public:
211 explicit ConstRefWrapper(const T& o) : ptr_(&o) {} 232 explicit ConstRefWrapper(const T& o) : ptr_(&o) {}
212 const T& get() { return *ptr_; } 233 const T& get() const { return *ptr_; }
213 private: 234 private:
214 const T* ptr_; 235 const T* ptr_;
215 }; 236 };
216 237
238 // An alternate implementation is to avoid the destructive copy, and instead
239 // specialize ParamTraits<> for OwnedWrapper<> to change the StorageType to
240 // a class that is essentially a scoped_ptr<>.
241 //
242 // This has the benefit though of leaving ParamTrais<> fully in
darin (slow to review) 2011/10/14 21:53:07 nit: ParamTrais -> ParamTraits
awong 2011/10/15 00:19:16 Done.
243 // callback_internal.h as well as avoiding type conversions during storage.
244 template <typename T>
245 class OwnedWrapper {
246 public:
247 explicit OwnedWrapper(T* o) : ptr_(o) {}
248 ~OwnedWrapper() { delete ptr_; }
249 T* get() const { return ptr_; }
250 OwnedWrapper(const OwnedWrapper& other) {
251 ptr_ = other.ptr_;
252 other.ptr_ = NULL;
253 }
254
255 private:
256 mutable T* ptr_;
257 };
258
217 259
218 // Unwrap the stored parameters for the wrappers above. 260 // Unwrap the stored parameters for the wrappers above.
219 template <typename T> 261 template <typename T>
220 T Unwrap(T o) { return o; } 262 T Unwrap(T o) { return o; }
221 263
222 template <typename T> 264 template <typename T>
223 T* Unwrap(UnretainedWrapper<T> unretained) { return unretained.get(); } 265 T* Unwrap(UnretainedWrapper<T> unretained) { return unretained.get(); }
224 266
225 template <typename T> 267 template <typename T>
226 const T& Unwrap(ConstRefWrapper<T> const_ref) { 268 const T& Unwrap(ConstRefWrapper<T> const_ref) {
227 return const_ref.get(); 269 return const_ref.get();
228 } 270 }
229 271
230 template <typename T> 272 template <typename T>
231 T* Unwrap(const scoped_refptr<T>& o) { return o.get(); } 273 T* Unwrap(const scoped_refptr<T>& o) { return o.get(); }
232 274
233 template <typename T> 275 template <typename T>
234 const WeakPtr<T>& Unwrap(const WeakPtr<T>& o) { return o; } 276 const WeakPtr<T>& Unwrap(const WeakPtr<T>& o) { return o; }
235 277
278 template <typename T>
279 T* Unwrap(const OwnedWrapper<T>& o) {
280 return o.get();
281 }
282
236 // Utility for handling different refcounting semantics in the Bind() 283 // Utility for handling different refcounting semantics in the Bind()
237 // function. 284 // function.
238 template <typename IsMethod, typename T> 285 template <typename IsMethod, typename T>
239 struct MaybeRefcount; 286 struct MaybeRefcount;
240 287
241 template <typename T> 288 template <typename T>
242 struct MaybeRefcount<base::false_type, T> { 289 struct MaybeRefcount<base::false_type, T> {
243 static void AddRef(const T&) {} 290 static void AddRef(const T&) {}
244 static void Release(const T&) {} 291 static void Release(const T&) {}
245 }; 292 };
246 293
247 template <typename T, size_t n> 294 template <typename T, size_t n>
248 struct MaybeRefcount<base::false_type, T[n]> { 295 struct MaybeRefcount<base::false_type, T[n]> {
249 static void AddRef(const T*) {} 296 static void AddRef(const T*) {}
250 static void Release(const T*) {} 297 static void Release(const T*) {}
251 }; 298 };
252 299
253 template <typename T> 300 template <typename T>
301 struct MaybeRefcount<base::true_type, T*> {
302 static void AddRef(T* o) { o->AddRef(); }
303 static void Release(T* o) { o->Release(); }
304 };
305
306 template <typename T>
254 struct MaybeRefcount<base::true_type, UnretainedWrapper<T> > { 307 struct MaybeRefcount<base::true_type, UnretainedWrapper<T> > {
255 static void AddRef(const UnretainedWrapper<T>&) {} 308 static void AddRef(const UnretainedWrapper<T>&) {}
256 static void Release(const UnretainedWrapper<T>&) {} 309 static void Release(const UnretainedWrapper<T>&) {}
257 }; 310 };
258 311
259 template <typename T> 312 template <typename T>
260 struct MaybeRefcount<base::true_type, T*> { 313 struct MaybeRefcount<base::true_type, OwnedWrapper<T> > {
261 static void AddRef(T* o) { o->AddRef(); } 314 static void AddRef(const OwnedWrapper<T>&) {}
262 static void Release(T* o) { o->Release(); } 315 static void Release(const OwnedWrapper<T>&) {}
263 }; 316 };
264 317
265 // No need to additionally AddRef() and Release() since we are storing a 318 // No need to additionally AddRef() and Release() since we are storing a
266 // scoped_refptr<> inside the storage object already. 319 // scoped_refptr<> inside the storage object already.
267 template <typename T> 320 template <typename T>
268 struct MaybeRefcount<base::true_type, scoped_refptr<T> > { 321 struct MaybeRefcount<base::true_type, scoped_refptr<T> > {
269 static void AddRef(const scoped_refptr<T>& o) {} 322 static void AddRef(const scoped_refptr<T>& o) {}
270 static void Release(const scoped_refptr<T>& o) {} 323 static void Release(const scoped_refptr<T>& o) {}
271 }; 324 };
272 325
(...skipping 19 matching lines...) Expand all
292 template <typename T> 345 template <typename T>
293 inline internal::UnretainedWrapper<T> Unretained(T* o) { 346 inline internal::UnretainedWrapper<T> Unretained(T* o) {
294 return internal::UnretainedWrapper<T>(o); 347 return internal::UnretainedWrapper<T>(o);
295 } 348 }
296 349
297 template <typename T> 350 template <typename T>
298 inline internal::ConstRefWrapper<T> ConstRef(const T& o) { 351 inline internal::ConstRefWrapper<T> ConstRef(const T& o) {
299 return internal::ConstRefWrapper<T>(o); 352 return internal::ConstRefWrapper<T>(o);
300 } 353 }
301 354
355 template <typename T>
356 inline internal::OwnedWrapper<T> Owned(T* o) {
357 return internal::OwnedWrapper<T>(o);
358 }
359
302 template <typename R> 360 template <typename R>
303 Closure IgnoreReturn(Callback<R(void)> callback) { 361 Closure IgnoreReturn(Callback<R(void)> callback) {
304 return Bind(&internal::VoidReturnAdapter<R>, callback); 362 return Bind(&internal::VoidReturnAdapter<R>, callback);
305 } 363 }
306 364
307 } // namespace base 365 } // namespace base
308 366
309 #endif // BASE_BIND_HELPERS_H_ 367 #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