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