OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 | 7 |
8 #include "base/callback_forward.h" | 8 #include "base/callback_forward.h" |
9 #include "base/callback_internal.h" | 9 #include "base/callback_internal.h" |
10 | 10 |
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
339 // void Foo(const char* ptr); | 339 // void Foo(const char* ptr); |
340 // void Bar(char* ptr); | 340 // void Bar(char* ptr); |
341 // Bind(&Foo, "test"); | 341 // Bind(&Foo, "test"); |
342 // Bind(&Bar, "test"); // This fails because ptr is not const. | 342 // Bind(&Bar, "test"); // This fails because ptr is not const. |
343 // | 343 // |
344 // If you are thinking of forward declaring Callback in your own header file, | 344 // If you are thinking of forward declaring Callback in your own header file, |
345 // please include "base/callback_forward.h" instead. | 345 // please include "base/callback_forward.h" instead. |
346 | 346 |
347 namespace base { | 347 namespace base { |
348 | 348 |
349 template <typename R, typename... Args, internal::CopyMode copy_mode> | 349 namespace internal { |
350 class Callback<R(Args...), copy_mode> | 350 |
351 : public internal::CallbackBase<copy_mode> { | 351 template <typename CallbackType> |
| 352 class RunMixin; |
| 353 |
| 354 template <typename R, typename... Args, CopyMode copy_mode> |
| 355 class RunMixin<Callback<R(Args...), copy_mode, RepeatMode::Repeating>> { |
352 private: | 356 private: |
353 using PolymorphicInvoke = R (*)(internal::BindStateBase*, Args&&...); | 357 using CallbackType = Callback<R(Args...), copy_mode, RepeatMode::Repeating>; |
| 358 using PolymorphicInvoke = R(*)(internal::BindStateBase*, Args&&...); |
354 | 359 |
355 public: | 360 public: |
356 // MSVC 2013 doesn't support Type Alias of function types. | 361 R Run(Args... args) const { |
357 // Revisit this after we update it to newer version. | 362 const CallbackType* cb = static_cast<const CallbackType*>(this); |
358 typedef R RunType(Args...); | 363 PolymorphicInvoke f = |
| 364 reinterpret_cast<PolymorphicInvoke>(cb->polymorphic_invoke_); |
| 365 return f(cb->bind_state_.get(), std::forward<Args>(args)...); |
| 366 } |
| 367 }; |
| 368 |
| 369 template <typename R, typename... Args> |
| 370 class RunMixin<Callback<R(Args...), CopyMode::MoveOnly, RepeatMode::OneShot>> { |
| 371 private: |
| 372 using CallbackType = |
| 373 Callback<R(Args...), CopyMode::MoveOnly, RepeatMode::OneShot>; |
| 374 using PolymorphicInvoke = R(*)(internal::BindStateBase*, Args&&...); |
| 375 |
| 376 public: |
| 377 R Run(Args... args) && { |
| 378 CallbackType cb = std::move(*static_cast<CallbackType*>(this)); |
| 379 PolymorphicInvoke f = |
| 380 reinterpret_cast<PolymorphicInvoke>(cb.polymorphic_invoke_); |
| 381 return f(cb.bind_state_.get(), std::forward<Args>(args)...); |
| 382 } |
| 383 }; |
| 384 |
| 385 } // namespace |
| 386 |
| 387 template <typename R, |
| 388 typename... Args, |
| 389 internal::CopyMode copy_mode, |
| 390 internal::RepeatMode repeat_mode> |
| 391 class Callback<R(Args...), copy_mode, repeat_mode> |
| 392 : public internal::CallbackBase<copy_mode>, |
| 393 public internal::RunMixin<Callback<R(Args...), copy_mode, repeat_mode>> { |
| 394 private: |
| 395 static_assert(repeat_mode != internal::RepeatMode::OneShot || |
| 396 copy_mode == internal::CopyMode::MoveOnly, |
| 397 "OneShot Callback must be MoveOnly."); |
| 398 using PolymorphicInvoke = R(*)(internal::BindStateBase*, Args&&...); |
| 399 |
| 400 template <internal::CopyMode other_copy_mode, |
| 401 internal::RepeatMode other_repeat_mode> |
| 402 using EnableIfConvertibleFrom = std::enable_if< |
| 403 (copy_mode != other_copy_mode || repeat_mode != other_repeat_mode) && |
| 404 (static_cast<int>(copy_mode) <= static_cast<int>(other_copy_mode)) && |
| 405 (static_cast<int>(repeat_mode) <= static_cast<int>(other_repeat_mode))>; |
| 406 |
| 407 public: |
| 408 using RunType = R(Args...); |
359 | 409 |
360 Callback() : internal::CallbackBase<copy_mode>(nullptr) {} | 410 Callback() : internal::CallbackBase<copy_mode>(nullptr) {} |
361 | 411 |
362 Callback(internal::BindStateBase* bind_state, | 412 Callback(internal::BindStateBase* bind_state, PolymorphicInvoke invoke_func) |
363 PolymorphicInvoke invoke_func) | |
364 : internal::CallbackBase<copy_mode>(bind_state) { | 413 : internal::CallbackBase<copy_mode>(bind_state) { |
365 using InvokeFuncStorage = | 414 using InvokeFuncStorage = |
366 typename internal::CallbackBase<copy_mode>::InvokeFuncStorage; | 415 typename internal::CallbackBase<copy_mode>::InvokeFuncStorage; |
367 this->polymorphic_invoke_ = | 416 this->polymorphic_invoke_ = |
368 reinterpret_cast<InvokeFuncStorage>(invoke_func); | 417 reinterpret_cast<InvokeFuncStorage>(invoke_func); |
369 } | 418 } |
370 | 419 |
| 420 template < |
| 421 internal::CopyMode other_copy_mode, |
| 422 internal::RepeatMode other_repeat_mode, |
| 423 typename = typename EnableIfConvertibleFrom<other_copy_mode, |
| 424 other_repeat_mode>::type> |
| 425 Callback(Callback<R(Args...), other_copy_mode, other_repeat_mode> other) |
| 426 : internal::CallbackBase<copy_mode>(std::move(other)) {} |
| 427 |
| 428 template < |
| 429 internal::CopyMode other_copy_mode, |
| 430 internal::RepeatMode other_repeat_mode, |
| 431 typename = typename EnableIfConvertibleFrom<other_copy_mode, |
| 432 other_repeat_mode>::type> |
| 433 Callback& operator=( |
| 434 Callback<R(Args...), other_copy_mode, other_repeat_mode> other) { |
| 435 static_cast<internal::CallbackBase<copy_mode>&>(*this) = std::move(other); |
| 436 return *this; |
| 437 } |
| 438 |
371 bool Equals(const Callback& other) const { | 439 bool Equals(const Callback& other) const { |
372 return this->EqualsInternal(other); | 440 return this->EqualsInternal(other); |
373 } | 441 } |
374 | 442 |
375 // Run() makes an extra copy compared to directly calling the bound function | 443 friend class internal::RunMixin<Callback>; |
376 // if an argument is passed-by-value and is copyable-but-not-movable: | |
377 // i.e. below copies CopyableNonMovableType twice. | |
378 // void F(CopyableNonMovableType) {} | |
379 // Bind(&F).Run(CopyableNonMovableType()); | |
380 // | |
381 // We can not fully apply Perfect Forwarding idiom to the callchain from | |
382 // Callback::Run() to the target function. Perfect Forwarding requires | |
383 // knowing how the caller will pass the arguments. However, the signature of | |
384 // InvokerType::Run() needs to be fixed in the callback constructor, so Run() | |
385 // cannot template its arguments based on how it's called. | |
386 R Run(Args... args) const { | |
387 PolymorphicInvoke f = | |
388 reinterpret_cast<PolymorphicInvoke>(this->polymorphic_invoke_); | |
389 return f(this->bind_state_.get(), std::forward<Args>(args)...); | |
390 } | |
391 }; | 444 }; |
392 | 445 |
393 } // namespace base | 446 } // namespace base |
394 | 447 |
395 #endif // BASE_CALLBACK_H_ | 448 #endif // BASE_CALLBACK_H_ |
OLD | NEW |