| Index: base/callback_helpers.h
|
| diff --git a/base/callback_helpers.h b/base/callback_helpers.h
|
| index 6e0aee88822d85cee8d5481241ac26741629d9b3..8d622f86552a5ec622b65a88d14ecf02316a2a99 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 AdaptCallbackForRepeatingHelper final {
|
| + public:
|
| + explicit AdaptCallbackForRepeatingHelper(OnceCallback<void(Args...)> callback)
|
| + : callback_(std::move(callback)) {
|
| + DCHECK(callback_);
|
| + }
|
| +
|
| + void Run(Args... args) {
|
| + if (subtle::NoBarrier_AtomicExchange(&has_run_, 1))
|
| + return;
|
| + DCHECK(callback_);
|
| + std::move(callback_).Run(std::forward<Args>(args)...);
|
| + }
|
| +
|
| + private:
|
| + volatile subtle::Atomic32 has_run_ = 0;
|
| + base::OnceCallback<void(Args...)> callback_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(AdaptCallbackForRepeatingHelper);
|
| +};
|
| +
|
| +} // 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...)> AdaptCallbackForRepeating(
|
| + OnceCallback<void(Args...)> callback) {
|
| + using Helper = internal::AdaptCallbackForRepeatingHelper<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 {
|
|
|