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

Side by Side Diff: base/callback.h

Issue 2042223002: Introduce OnceClosure and BindOnce (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 4 years, 5 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
OLDNEW
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
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_
OLDNEW
« base/bind.h ('K') | « base/bind_unittest.cc ('k') | base/callback_forward.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698