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

Side by Side Diff: base/bind_helpers.h

Issue 8483003: Callback API Change: Reimplement Bind(); support IgnoreResult, full currying, and use less types (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address initial comments. Created 9 years, 1 month 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) 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::Owned(), 9 // The public functions are base::Unretained(), base::Owned(),
10 // base::ConstRef(), and base::IgnoreReturn(). 10 // base::ConstRef(), and base::IgnoreReturn().
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
191 template <typename C> 191 template <typename C>
192 static No& Check(Helper<&C::AddRef>*); 192 static No& Check(Helper<&C::AddRef>*);
193 193
194 template <typename > 194 template <typename >
195 static Yes& Check(...); 195 static Yes& Check(...);
196 196
197 public: 197 public:
198 static const bool value = sizeof(Check<Base>(0)) == sizeof(Yes); 198 static const bool value = sizeof(Check<Base>(0)) == sizeof(Yes);
199 }; 199 };
200 200
201
202 // Helpers to assert that arguments of a recounted type are bound with a 201 // Helpers to assert that arguments of a recounted type are bound with a
203 // scoped_refptr. 202 // scoped_refptr.
204 template <bool IsClasstype, typename T> 203 template <bool IsClasstype, typename T>
205 struct UnsafeBindtoRefCountedArgHelper : false_type { 204 struct UnsafeBindtoRefCountedArgHelper : false_type {
206 }; 205 };
207 206
208 template <typename T> 207 template <typename T>
209 struct UnsafeBindtoRefCountedArgHelper<true, T> 208 struct UnsafeBindtoRefCountedArgHelper<true, T>
210 : integral_constant<bool, SupportsAddRefAndRelease<T>::value> { 209 : integral_constant<bool, SupportsAddRefAndRelease<T>::value> {
211 }; 210 };
212 211
213 template <typename T> 212 template <typename T>
214 struct UnsafeBindtoRefCountedArg : false_type { 213 struct UnsafeBindtoRefCountedArg : false_type {
215 }; 214 };
216 215
217 template <typename T> 216 template <typename T>
218 struct UnsafeBindtoRefCountedArg<T*> 217 struct UnsafeBindtoRefCountedArg<T*>
219 : UnsafeBindtoRefCountedArgHelper<is_class<T>::value, T> { 218 : UnsafeBindtoRefCountedArgHelper<is_class<T>::value, T> {
220 }; 219 };
221 220
221 template <typename T>
222 class HasIsMethodTag {
willchan no longer on Chromium 2011/11/11 01:30:25 It's not obvious to me what's better. Just using a
awong 2011/11/11 02:17:57 I didn't want to introduce an IsMethod typedef int
223 typedef char Yes[1];
224 typedef char No[2];
225
226 template <typename U>
227 static Yes& Check(typename U::IsMethod*);
228
229 template <typename U>
230 static No& Check(...);
231
232 public:
233 static const bool value = sizeof(Check<T>(0)) == sizeof(Yes);
234 };
222 235
223 template <typename T> 236 template <typename T>
224 class UnretainedWrapper { 237 class UnretainedWrapper {
225 public: 238 public:
226 explicit UnretainedWrapper(T* o) : ptr_(o) {} 239 explicit UnretainedWrapper(T* o) : ptr_(o) {}
227 T* get() const { return ptr_; } 240 T* get() const { return ptr_; }
228 private: 241 private:
229 T* ptr_; 242 T* ptr_;
230 }; 243 };
231 244
232 template <typename T> 245 template <typename T>
233 class ConstRefWrapper { 246 class ConstRefWrapper {
234 public: 247 public:
235 explicit ConstRefWrapper(const T& o) : ptr_(&o) {} 248 explicit ConstRefWrapper(const T& o) : ptr_(&o) {}
236 const T& get() const { return *ptr_; } 249 const T& get() const { return *ptr_; }
237 private: 250 private:
238 const T* ptr_; 251 const T* ptr_;
239 }; 252 };
240 253
254 template <typename T>
255 struct IgnoreResultHelper {
256 explicit IgnoreResultHelper(T functor) : functor_(functor) {}
257
258 T functor_;
259 };
260
261 template <typename T>
262 struct IgnoreResultHelper<Callback<T> > {
263 explicit IgnoreResultHelper(const Callback<T>& functor) : functor_(functor) {}
264
265 const Callback<T>& functor_;
266 };
267
241 // An alternate implementation is to avoid the destructive copy, and instead 268 // An alternate implementation is to avoid the destructive copy, and instead
242 // specialize ParamTraits<> for OwnedWrapper<> to change the StorageType to 269 // specialize ParamTraits<> for OwnedWrapper<> to change the StorageType to
243 // a class that is essentially a scoped_ptr<>. 270 // a class that is essentially a scoped_ptr<>.
244 // 271 //
245 // The current implementation has the benefit though of leaving ParamTraits<> 272 // The current implementation has the benefit though of leaving ParamTraits<>
246 // fully in callback_internal.h as well as avoiding type conversions during 273 // fully in callback_internal.h as well as avoiding type conversions during
247 // storage. 274 // storage.
248 template <typename T> 275 template <typename T>
249 class OwnedWrapper { 276 class OwnedWrapper {
250 public: 277 public:
251 explicit OwnedWrapper(T* o) : ptr_(o) {} 278 explicit OwnedWrapper(T* o) : ptr_(o) {}
252 ~OwnedWrapper() { delete ptr_; } 279 ~OwnedWrapper() { delete ptr_; }
253 T* get() const { return ptr_; } 280 T* get() const { return ptr_; }
254 OwnedWrapper(const OwnedWrapper& other) { 281 OwnedWrapper(const OwnedWrapper& other) {
255 ptr_ = other.ptr_; 282 ptr_ = other.ptr_;
256 other.ptr_ = NULL; 283 other.ptr_ = NULL;
257 } 284 }
258 285
259 private: 286 private:
260 mutable T* ptr_; 287 mutable T* ptr_;
261 }; 288 };
262 289
263
264 // Unwrap the stored parameters for the wrappers above. 290 // Unwrap the stored parameters for the wrappers above.
265 template <typename T> 291 template <typename T>
266 T Unwrap(T o) { return o; } 292 struct UnwrapTraits {
293 typedef const T& ForwardType;
294 static ForwardType Unwrap(const T& o) { return o; }
295 };
267 296
268 template <typename T> 297 template <typename T>
269 T* Unwrap(UnretainedWrapper<T> unretained) { return unretained.get(); } 298 struct UnwrapTraits<UnretainedWrapper<T> > {
299 typedef T* ForwardType;
300 static ForwardType Unwrap(UnretainedWrapper<T> unretained) {
301 return unretained.get();
302 }
303 };
270 304
271 template <typename T> 305 template <typename T>
272 const T& Unwrap(ConstRefWrapper<T> const_ref) { 306 struct UnwrapTraits<ConstRefWrapper<T> > {
273 return const_ref.get(); 307 typedef const T& ForwardType;
274 } 308 static ForwardType Unwrap(ConstRefWrapper<T> const_ref) {
309 return const_ref.get();
310 }
311 };
275 312
276 template <typename T> 313 template <typename T>
277 T* Unwrap(const scoped_refptr<T>& o) { return o.get(); } 314 struct UnwrapTraits<scoped_refptr<T> > {
315 typedef T* ForwardType;
316 static ForwardType Unwrap(const scoped_refptr<T>& o) { return o.get(); }
317 };
278 318
279 template <typename T> 319 template <typename T>
280 const WeakPtr<T>& Unwrap(const WeakPtr<T>& o) { return o; } 320 struct UnwrapTraits<WeakPtr<T> > {
321 typedef const WeakPtr<T>& ForwardType;
322 static ForwardType Unwrap(const WeakPtr<T>& o) { return o; }
323 };
281 324
282 template <typename T> 325 template <typename T>
283 T* Unwrap(const OwnedWrapper<T>& o) { 326 struct UnwrapTraits<OwnedWrapper<T> > {
284 return o.get(); 327 typedef T* ForwardType;
285 } 328 static ForwardType Unwrap(const OwnedWrapper<T>& o) {
329 return o.get();
330 }
331 };
286 332
287 // Utility for handling different refcounting semantics in the Bind() 333 // Utility for handling different refcounting semantics in the Bind()
288 // function. 334 // function.
289 template <typename IsMethod, typename T> 335 template <bool, typename T>
290 struct MaybeRefcount; 336 struct MaybeRefcount;
291 337
292 template <typename T> 338 template <typename T>
293 struct MaybeRefcount<base::false_type, T> { 339 struct MaybeRefcount<false, T> {
294 static void AddRef(const T&) {} 340 static void AddRef(const T&) {}
295 static void Release(const T&) {} 341 static void Release(const T&) {}
296 }; 342 };
297 343
298 template <typename T, size_t n> 344 template <typename T, size_t n>
299 struct MaybeRefcount<base::false_type, T[n]> { 345 struct MaybeRefcount<false, T[n]> {
300 static void AddRef(const T*) {} 346 static void AddRef(const T*) {}
301 static void Release(const T*) {} 347 static void Release(const T*) {}
302 }; 348 };
303 349
304 template <typename T> 350 template <typename T>
305 struct MaybeRefcount<base::true_type, T*> { 351 struct MaybeRefcount<true, T*> {
306 static void AddRef(T* o) { o->AddRef(); } 352 static void AddRef(T* o) { o->AddRef(); }
307 static void Release(T* o) { o->Release(); } 353 static void Release(T* o) { o->Release(); }
308 }; 354 };
309 355
310 template <typename T> 356 template <typename T>
311 struct MaybeRefcount<base::true_type, UnretainedWrapper<T> > { 357 struct MaybeRefcount<true, UnretainedWrapper<T> > {
312 static void AddRef(const UnretainedWrapper<T>&) {} 358 static void AddRef(const UnretainedWrapper<T>&) {}
313 static void Release(const UnretainedWrapper<T>&) {} 359 static void Release(const UnretainedWrapper<T>&) {}
314 }; 360 };
315 361
316 template <typename T> 362 template <typename T>
317 struct MaybeRefcount<base::true_type, OwnedWrapper<T> > { 363 struct MaybeRefcount<true, OwnedWrapper<T> > {
318 static void AddRef(const OwnedWrapper<T>&) {} 364 static void AddRef(const OwnedWrapper<T>&) {}
319 static void Release(const OwnedWrapper<T>&) {} 365 static void Release(const OwnedWrapper<T>&) {}
320 }; 366 };
321 367
322 // No need to additionally AddRef() and Release() since we are storing a 368 // No need to additionally AddRef() and Release() since we are storing a
323 // scoped_refptr<> inside the storage object already. 369 // scoped_refptr<> inside the storage object already.
324 template <typename T> 370 template <typename T>
325 struct MaybeRefcount<base::true_type, scoped_refptr<T> > { 371 struct MaybeRefcount<true, scoped_refptr<T> > {
326 static void AddRef(const scoped_refptr<T>& o) {} 372 static void AddRef(const scoped_refptr<T>& o) {}
327 static void Release(const scoped_refptr<T>& o) {} 373 static void Release(const scoped_refptr<T>& o) {}
328 }; 374 };
329 375
330 template <typename T> 376 template <typename T>
331 struct MaybeRefcount<base::true_type, const T*> { 377 struct MaybeRefcount<true, const T*> {
332 static void AddRef(const T* o) { o->AddRef(); } 378 static void AddRef(const T* o) { o->AddRef(); }
333 static void Release(const T* o) { o->Release(); } 379 static void Release(const T* o) { o->Release(); }
334 }; 380 };
335 381
336 template <typename T> 382 template <typename T>
337 struct MaybeRefcount<base::true_type, WeakPtr<T> > { 383 struct MaybeRefcount<true, WeakPtr<T> > {
338 static void AddRef(const WeakPtr<T>&) {} 384 static void AddRef(const WeakPtr<T>&) {}
339 static void Release(const WeakPtr<T>&) {} 385 static void Release(const WeakPtr<T>&) {}
340 }; 386 };
341 387
342 template <typename R> 388 template <typename R>
343 void VoidReturnAdapter(Callback<R(void)> callback) { 389 void VoidReturnAdapter(Callback<R(void)> callback) {
344 callback.Run(); 390 callback.Run();
345 } 391 }
346 392
393 // IsWeakMethod determines is a helper to determine if we are binding a
394 // WeakPtr<> to a method. It is unsed internally by Bind() to select the
395 // correct InvokeHelper that will no-op itself in the event the WeakPtr<>
396 // for the target object is invalidated.
397 //
398 // P1 should be the type of the object that will be received of the method.
399 template <bool IsMethod, typename P1>
400 struct IsWeakMethod : public false_type {};
401
402 template <typename T>
403 struct IsWeakMethod<true, WeakPtr<T> > : public true_type {};
404
405 template <typename T>
406 struct IsWeakMethod<true, ConstRefWrapper<WeakPtr<T> > > : public true_type {};
407
347 } // namespace internal 408 } // namespace internal
348 409
349 template <typename T> 410 template <typename T>
350 inline internal::UnretainedWrapper<T> Unretained(T* o) { 411 static inline internal::UnretainedWrapper<T> Unretained(T* o) {
351 return internal::UnretainedWrapper<T>(o); 412 return internal::UnretainedWrapper<T>(o);
352 } 413 }
353 414
354 template <typename T> 415 template <typename T>
355 inline internal::ConstRefWrapper<T> ConstRef(const T& o) { 416 static inline internal::ConstRefWrapper<T> ConstRef(const T& o) {
356 return internal::ConstRefWrapper<T>(o); 417 return internal::ConstRefWrapper<T>(o);
357 } 418 }
358 419
359 template <typename T> 420 template <typename T>
360 inline internal::OwnedWrapper<T> Owned(T* o) { 421 static inline internal::OwnedWrapper<T> Owned(T* o) {
361 return internal::OwnedWrapper<T>(o); 422 return internal::OwnedWrapper<T>(o);
362 } 423 }
363 424
364 template <typename R> 425 template <typename R>
365 Closure IgnoreReturn(Callback<R(void)> callback) { 426 static inline Closure IgnoreReturn(Callback<R(void)> callback) {
366 return Bind(&internal::VoidReturnAdapter<R>, callback); 427 return Bind(&internal::VoidReturnAdapter<R>, callback);
367 } 428 }
368 429
430 template <typename T>
431 static inline internal::IgnoreResultHelper<T> IgnoreResult(T data) {
432 return internal::IgnoreResultHelper<T>(data);
433 }
434
435 template <typename T>
436 static inline internal::IgnoreResultHelper<Callback<T> >
437 IgnoreResult(const Callback<T>& data) {
438 return internal::IgnoreResultHelper<Callback<T> >(data);
439 }
440
441
369 } // namespace base 442 } // namespace base
370 443
371 #endif // BASE_BIND_HELPERS_H_ 444 #endif // BASE_BIND_HELPERS_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698