| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // This defines helpful methods for dealing with Callbacks. Because Callbacks |
| // are implemented using templates, with a class per callback signature, adding |
| // methods to Callback<> itself is unattractive (lots of extra code gets |
| // generated). Instead, consider adding methods here. |
| |
| #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 { |
| |
| // Prefer std::move() over ResetAndReturn(). |
| template <typename CallbackType> |
| CallbackType ResetAndReturn(CallbackType* cb) { |
| CallbackType ret(std::move(*cb)); |
| DCHECK(!*cb); |
| return ret; |
| } |
| |
| #ifdef STARBOARD |
| template <typename CallbackType> |
| bool ResetAndRunIfNotNull(CallbackType* cb) { |
| if (cb->is_null()) { |
| return false; |
| } |
| CallbackType ret(std::move(*cb)); |
| DCHECK(!*cb); |
| ret.Run(); |
| return true; |
| } |
| |
| template <typename Sig, typename... ParamTypes> |
| bool ResetAndRunIfNotNull(base::Callback<Sig>* cb, |
| const ParamTypes&... params) { |
| if (cb->is_null()) { |
| return false; |
| } |
| base::Callback<Sig> ret(std::move(*cb)); |
| DCHECK(!*cb); |
| ret.Run(params...); |
| return true; |
| } |
| #endif |
| |
| 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. |
| // |
| // Note that this deliberately subverts the Once/Repeating paradigm of Callbacks |
| // but helps ease the migration from old-style Callbacks. Avoid if possible; use |
| // if necessary for migration. TODO(tzik): Remove it. https://crbug.com/730593 |
| template <typename... Args> |
| RepeatingCallback<void(Args...)> AdaptCallbackForRepeating( |
| OnceCallback<void(Args...)> callback) { |
| using Helper = internal::AdaptCallbackForRepeatingHelper<Args...>; |
| return base::BindRepeating(&Helper::Run, |
| std::make_unique<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 { |
| public: |
| ScopedClosureRunner(); |
| explicit ScopedClosureRunner(OnceClosure closure); |
| ~ScopedClosureRunner(); |
| |
| ScopedClosureRunner(ScopedClosureRunner&& other); |
| |
| // Releases the current closure if it's set and replaces it with the closure |
| // from |other|. |
| ScopedClosureRunner& operator=(ScopedClosureRunner&& other); |
| |
| // Calls the current closure and resets it, so it wont be called again. |
| void RunAndReset(); |
| |
| // Replaces closure with the new one releasing the old one without calling it. |
| void ReplaceClosure(OnceClosure closure); |
| |
| // Releases the Closure without calling. |
| OnceClosure Release() WARN_UNUSED_RESULT; |
| |
| private: |
| OnceClosure closure_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ScopedClosureRunner); |
| }; |
| |
| } // namespace base |
| |
| #endif // BASE_CALLBACK_HELPERS_H_ |