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

Unified Diff: base/callback_helpers.h

Issue 2820993002: Introduce base::IgnoreReuse() to wrap OnceCallback into RepeatingCallback (Closed)
Patch Set: Created 3 years, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | base/callback_helpers_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 {
« no previous file with comments | « no previous file | base/callback_helpers_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698