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 { |