OLD | NEW |
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 Loading... |
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 { |
| 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 is a helper that determine if we are binding a WeakPtr<> to a |
| 394 // method. It is unsed internally by Bind() to select the correct |
| 395 // InvokeHelper that will no-op itself in the event the WeakPtr<> for |
| 396 // 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_ |
OLD | NEW |