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 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
338 // Example: | 338 // Example: |
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 namespace internal { | |
349 template <typename Runnable, typename RunType, typename... BoundArgsType> | |
350 struct BindState; | |
351 } // namespace internal | |
352 | 348 |
353 template <typename R, typename... Args, internal::CopyMode copy_mode> | 349 template <typename R, typename... Args, internal::CopyMode copy_mode> |
354 class Callback<R(Args...), copy_mode> | 350 class Callback<R(Args...), copy_mode> |
355 : public internal::CallbackBase<copy_mode> { | 351 : public internal::CallbackBase<copy_mode> { |
| 352 private: |
| 353 using PolymorphicInvoke = R (*)(internal::BindStateBase*, Args&&...); |
| 354 |
356 public: | 355 public: |
357 // MSVC 2013 doesn't support Type Alias of function types. | 356 // MSVC 2013 doesn't support Type Alias of function types. |
358 // Revisit this after we update it to newer version. | 357 // Revisit this after we update it to newer version. |
359 typedef R RunType(Args...); | 358 typedef R RunType(Args...); |
360 | 359 |
361 Callback() : internal::CallbackBase<copy_mode>(nullptr) {} | 360 Callback() : internal::CallbackBase<copy_mode>(nullptr) {} |
362 | 361 |
363 template <typename Runnable, typename BindRunType, typename... BoundArgs> | 362 Callback(internal::BindStateBase* bind_state, |
364 explicit Callback( | 363 PolymorphicInvoke invoke_func) |
365 internal::BindState<Runnable, BindRunType, BoundArgs...>* bind_state) | |
366 : internal::CallbackBase<copy_mode>(bind_state) { | 364 : internal::CallbackBase<copy_mode>(bind_state) { |
367 // Force the assignment to a local variable of PolymorphicInvoke | |
368 // so the compiler will typecheck that the passed in Run() method has | |
369 // the correct type. | |
370 PolymorphicInvoke invoke_func = | |
371 &internal::BindState<Runnable, BindRunType, BoundArgs...> | |
372 ::InvokerType::Run; | |
373 using InvokeFuncStorage = | 365 using InvokeFuncStorage = |
374 typename internal::CallbackBase<copy_mode>::InvokeFuncStorage; | 366 typename internal::CallbackBase<copy_mode>::InvokeFuncStorage; |
375 this->polymorphic_invoke_ = | 367 this->polymorphic_invoke_ = |
376 reinterpret_cast<InvokeFuncStorage>(invoke_func); | 368 reinterpret_cast<InvokeFuncStorage>(invoke_func); |
377 } | 369 } |
378 | 370 |
379 bool Equals(const Callback& other) const { | 371 bool Equals(const Callback& other) const { |
380 return this->EqualsInternal(other); | 372 return this->EqualsInternal(other); |
381 } | 373 } |
382 | 374 |
383 // Run() makes an extra copy compared to directly calling the bound function | 375 // Run() makes an extra copy compared to directly calling the bound function |
384 // if an argument is passed-by-value and is copyable-but-not-movable: | 376 // if an argument is passed-by-value and is copyable-but-not-movable: |
385 // i.e. below copies CopyableNonMovableType twice. | 377 // i.e. below copies CopyableNonMovableType twice. |
386 // void F(CopyableNonMovableType) {} | 378 // void F(CopyableNonMovableType) {} |
387 // Bind(&F).Run(CopyableNonMovableType()); | 379 // Bind(&F).Run(CopyableNonMovableType()); |
388 // | 380 // |
389 // We can not fully apply Perfect Forwarding idiom to the callchain from | 381 // We can not fully apply Perfect Forwarding idiom to the callchain from |
390 // Callback::Run() to the target function. Perfect Forwarding requires | 382 // Callback::Run() to the target function. Perfect Forwarding requires |
391 // knowing how the caller will pass the arguments. However, the signature of | 383 // knowing how the caller will pass the arguments. However, the signature of |
392 // InvokerType::Run() needs to be fixed in the callback constructor, so Run() | 384 // InvokerType::Run() needs to be fixed in the callback constructor, so Run() |
393 // cannot template its arguments based on how it's called. | 385 // cannot template its arguments based on how it's called. |
394 R Run(Args... args) const { | 386 R Run(Args... args) const { |
395 PolymorphicInvoke f = | 387 PolymorphicInvoke f = |
396 reinterpret_cast<PolymorphicInvoke>(this->polymorphic_invoke_); | 388 reinterpret_cast<PolymorphicInvoke>(this->polymorphic_invoke_); |
397 return f(this->bind_state_.get(), std::forward<Args>(args)...); | 389 return f(this->bind_state_.get(), std::forward<Args>(args)...); |
398 } | 390 } |
399 | |
400 private: | |
401 using PolymorphicInvoke = R (*)(internal::BindStateBase*, Args&&...); | |
402 }; | 391 }; |
403 | 392 |
404 } // namespace base | 393 } // namespace base |
405 | 394 |
406 #endif // BASE_CALLBACK_H_ | 395 #endif // BASE_CALLBACK_H_ |
OLD | NEW |