xref: /aosp_15_r20/external/libchrome/base/callback_helpers.h (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker // This defines helpful methods for dealing with Callbacks.  Because Callbacks
6*635a8641SAndroid Build Coastguard Worker // are implemented using templates, with a class per callback signature, adding
7*635a8641SAndroid Build Coastguard Worker // methods to Callback<> itself is unattractive (lots of extra code gets
8*635a8641SAndroid Build Coastguard Worker // generated).  Instead, consider adding methods here.
9*635a8641SAndroid Build Coastguard Worker 
10*635a8641SAndroid Build Coastguard Worker #ifndef BASE_CALLBACK_HELPERS_H_
11*635a8641SAndroid Build Coastguard Worker #define BASE_CALLBACK_HELPERS_H_
12*635a8641SAndroid Build Coastguard Worker 
13*635a8641SAndroid Build Coastguard Worker #include <utility>
14*635a8641SAndroid Build Coastguard Worker 
15*635a8641SAndroid Build Coastguard Worker #include "base/atomicops.h"
16*635a8641SAndroid Build Coastguard Worker #include "base/bind.h"
17*635a8641SAndroid Build Coastguard Worker #include "base/callback.h"
18*635a8641SAndroid Build Coastguard Worker #include "base/compiler_specific.h"
19*635a8641SAndroid Build Coastguard Worker #include "base/macros.h"
20*635a8641SAndroid Build Coastguard Worker #include "base/memory/ptr_util.h"
21*635a8641SAndroid Build Coastguard Worker 
22*635a8641SAndroid Build Coastguard Worker namespace base {
23*635a8641SAndroid Build Coastguard Worker 
24*635a8641SAndroid Build Coastguard Worker // Prefer std::move() over ResetAndReturn().
25*635a8641SAndroid Build Coastguard Worker template <typename CallbackType>
ResetAndReturn(CallbackType * cb)26*635a8641SAndroid Build Coastguard Worker CallbackType ResetAndReturn(CallbackType* cb) {
27*635a8641SAndroid Build Coastguard Worker   CallbackType ret(std::move(*cb));
28*635a8641SAndroid Build Coastguard Worker   DCHECK(!*cb);
29*635a8641SAndroid Build Coastguard Worker   return ret;
30*635a8641SAndroid Build Coastguard Worker }
31*635a8641SAndroid Build Coastguard Worker 
32*635a8641SAndroid Build Coastguard Worker namespace internal {
33*635a8641SAndroid Build Coastguard Worker 
34*635a8641SAndroid Build Coastguard Worker template <typename... Args>
35*635a8641SAndroid Build Coastguard Worker class AdaptCallbackForRepeatingHelper final {
36*635a8641SAndroid Build Coastguard Worker  public:
AdaptCallbackForRepeatingHelper(OnceCallback<void (Args...)> callback)37*635a8641SAndroid Build Coastguard Worker   explicit AdaptCallbackForRepeatingHelper(OnceCallback<void(Args...)> callback)
38*635a8641SAndroid Build Coastguard Worker       : callback_(std::move(callback)) {
39*635a8641SAndroid Build Coastguard Worker     DCHECK(callback_);
40*635a8641SAndroid Build Coastguard Worker   }
41*635a8641SAndroid Build Coastguard Worker 
Run(Args...args)42*635a8641SAndroid Build Coastguard Worker   void Run(Args... args) {
43*635a8641SAndroid Build Coastguard Worker     if (subtle::NoBarrier_AtomicExchange(&has_run_, 1))
44*635a8641SAndroid Build Coastguard Worker       return;
45*635a8641SAndroid Build Coastguard Worker     DCHECK(callback_);
46*635a8641SAndroid Build Coastguard Worker     std::move(callback_).Run(std::forward<Args>(args)...);
47*635a8641SAndroid Build Coastguard Worker   }
48*635a8641SAndroid Build Coastguard Worker 
49*635a8641SAndroid Build Coastguard Worker  private:
50*635a8641SAndroid Build Coastguard Worker   volatile subtle::Atomic32 has_run_ = 0;
51*635a8641SAndroid Build Coastguard Worker   base::OnceCallback<void(Args...)> callback_;
52*635a8641SAndroid Build Coastguard Worker 
53*635a8641SAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(AdaptCallbackForRepeatingHelper);
54*635a8641SAndroid Build Coastguard Worker };
55*635a8641SAndroid Build Coastguard Worker 
56*635a8641SAndroid Build Coastguard Worker }  // namespace internal
57*635a8641SAndroid Build Coastguard Worker 
58*635a8641SAndroid Build Coastguard Worker // Wraps the given OnceCallback into a RepeatingCallback that relays its
59*635a8641SAndroid Build Coastguard Worker // invocation to the original OnceCallback on the first invocation. The
60*635a8641SAndroid Build Coastguard Worker // following invocations are just ignored.
61*635a8641SAndroid Build Coastguard Worker //
62*635a8641SAndroid Build Coastguard Worker // Note that this deliberately subverts the Once/Repeating paradigm of Callbacks
63*635a8641SAndroid Build Coastguard Worker // but helps ease the migration from old-style Callbacks. Avoid if possible; use
64*635a8641SAndroid Build Coastguard Worker // if necessary for migration. TODO(tzik): Remove it. https://crbug.com/730593
65*635a8641SAndroid Build Coastguard Worker template <typename... Args>
AdaptCallbackForRepeating(OnceCallback<void (Args...)> callback)66*635a8641SAndroid Build Coastguard Worker RepeatingCallback<void(Args...)> AdaptCallbackForRepeating(
67*635a8641SAndroid Build Coastguard Worker     OnceCallback<void(Args...)> callback) {
68*635a8641SAndroid Build Coastguard Worker   using Helper = internal::AdaptCallbackForRepeatingHelper<Args...>;
69*635a8641SAndroid Build Coastguard Worker   return base::BindRepeating(&Helper::Run,
70*635a8641SAndroid Build Coastguard Worker                              std::make_unique<Helper>(std::move(callback)));
71*635a8641SAndroid Build Coastguard Worker }
72*635a8641SAndroid Build Coastguard Worker 
73*635a8641SAndroid Build Coastguard Worker // ScopedClosureRunner is akin to std::unique_ptr<> for Closures. It ensures
74*635a8641SAndroid Build Coastguard Worker // that the Closure is executed no matter how the current scope exits.
75*635a8641SAndroid Build Coastguard Worker class BASE_EXPORT ScopedClosureRunner {
76*635a8641SAndroid Build Coastguard Worker  public:
77*635a8641SAndroid Build Coastguard Worker   ScopedClosureRunner();
78*635a8641SAndroid Build Coastguard Worker   explicit ScopedClosureRunner(OnceClosure closure);
79*635a8641SAndroid Build Coastguard Worker   ~ScopedClosureRunner();
80*635a8641SAndroid Build Coastguard Worker 
81*635a8641SAndroid Build Coastguard Worker   ScopedClosureRunner(ScopedClosureRunner&& other);
82*635a8641SAndroid Build Coastguard Worker 
83*635a8641SAndroid Build Coastguard Worker   // Releases the current closure if it's set and replaces it with the closure
84*635a8641SAndroid Build Coastguard Worker   // from |other|.
85*635a8641SAndroid Build Coastguard Worker   ScopedClosureRunner& operator=(ScopedClosureRunner&& other);
86*635a8641SAndroid Build Coastguard Worker 
87*635a8641SAndroid Build Coastguard Worker   // Calls the current closure and resets it, so it wont be called again.
88*635a8641SAndroid Build Coastguard Worker   void RunAndReset();
89*635a8641SAndroid Build Coastguard Worker 
90*635a8641SAndroid Build Coastguard Worker   // Replaces closure with the new one releasing the old one without calling it.
91*635a8641SAndroid Build Coastguard Worker   void ReplaceClosure(OnceClosure closure);
92*635a8641SAndroid Build Coastguard Worker 
93*635a8641SAndroid Build Coastguard Worker   // Releases the Closure without calling.
94*635a8641SAndroid Build Coastguard Worker   OnceClosure Release() WARN_UNUSED_RESULT;
95*635a8641SAndroid Build Coastguard Worker 
96*635a8641SAndroid Build Coastguard Worker  private:
97*635a8641SAndroid Build Coastguard Worker   OnceClosure closure_;
98*635a8641SAndroid Build Coastguard Worker 
99*635a8641SAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(ScopedClosureRunner);
100*635a8641SAndroid Build Coastguard Worker };
101*635a8641SAndroid Build Coastguard Worker 
102*635a8641SAndroid Build Coastguard Worker }  // namespace base
103*635a8641SAndroid Build Coastguard Worker 
104*635a8641SAndroid Build Coastguard Worker #endif  // BASE_CALLBACK_HELPERS_H_
105