Chromium Code Reviews| Index: base/callback_helpers.h |
| diff --git a/base/callback_helpers.h b/base/callback_helpers.h |
| index 6e0aee88822d85cee8d5481241ac26741629d9b3..7761f7fbbf63321aac2636b72f775febd4f482c8 100644 |
| --- a/base/callback_helpers.h |
| +++ b/base/callback_helpers.h |
| @@ -14,22 +14,64 @@ |
| #ifndef BASE_CALLBACK_HELPERS_H_ |
| #define BASE_CALLBACK_HELPERS_H_ |
| +#include <utility> |
| + |
| +#include "base/atomicops.h" |
| +#include "base/bind.h" |
| #include "base/callback.h" |
| #include "base/compiler_specific.h" |
| #include "base/macros.h" |
| +#include "base/memory/ptr_util.h" |
| namespace base { |
| template <typename Signature, |
| internal::CopyMode copy_mode, |
| internal::RepeatMode repeat_mode> |
| -base::Callback<Signature, copy_mode, repeat_mode> ResetAndReturn( |
| - base::Callback<Signature, copy_mode, repeat_mode>* cb) { |
| - base::Callback<Signature, copy_mode, repeat_mode> ret(std::move(*cb)); |
| +Callback<Signature, copy_mode, repeat_mode> ResetAndReturn( |
| + Callback<Signature, copy_mode, repeat_mode>* cb) { |
| + Callback<Signature, copy_mode, repeat_mode> ret(std::move(*cb)); |
| DCHECK(!*cb); |
| return ret; |
| } |
| +namespace internal { |
| + |
| +template <typename... Args> |
| +class IgnoreReuseHelper final { |
| + public: |
| + explicit IgnoreReuseHelper(OnceCallback<void(Args...)> callback) |
| + : callback_(std::move(callback)) { |
| + DCHECK(callback_); |
| + } |
| + |
| + void Run(Args... args) { |
| + if (!subtle::NoBarrier_AtomicExchange(&is_first_, 0)) |
|
dcheng
2017/04/18 06:45:39
Nit: maybe naming would be slightly clearer by cal
tzik
2017/04/20 06:06:05
Done.
|
| + return; |
| + DCHECK(callback_); |
| + std::move(callback_).Run(std::forward<Args>(args)...); |
| + } |
| + |
| + private: |
| + volatile subtle::Atomic32 is_first_ = 1; |
| + base::OnceCallback<void(Args...)> callback_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(IgnoreReuseHelper); |
| +}; |
| + |
| +} // namespace internal |
| + |
| +// Wraps the given OnceCallback into a RepeatingCallback that relays its |
| +// invocation to the original OnceCallback on the first invocation. The |
| +// following invocations are just ignored. |
| +template <typename... Args> |
| +RepeatingCallback<void(Args...)> IgnoreReuse( |
| + OnceCallback<void(Args...)> callback) { |
| + using Helper = internal::IgnoreReuseHelper<Args...>; |
| + return base::BindRepeating(&Helper::Run, |
| + base::MakeUnique<Helper>(std::move(callback))); |
| +} |
| + |
| // ScopedClosureRunner is akin to std::unique_ptr<> for Closures. It ensures |
| // that the Closure is executed no matter how the current scope exits. |
| class BASE_EXPORT ScopedClosureRunner { |