• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2012
2 // Google Inc. All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 //    * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 //    * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 //    * Neither the name of Google Inc. nor the name Chromium Embedded
15 // Framework nor the names of its contributors may be used to endorse
16 // or promote products derived from this software without specific prior
17 // written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // This defines helpful methods for dealing with Callbacks.  Because Callbacks
32 // are implemented using templates, with a class per callback signature, adding
33 // methods to Callback<> itself is unattractive (lots of extra code gets
34 // generated).  Instead, consider adding methods here.
35 
36 #ifndef CEF_INCLUDE_BASE_CEF_CALLBACK_HELPERS_H_
37 #define CEF_INCLUDE_BASE_CEF_CALLBACK_HELPERS_H_
38 #pragma once
39 
40 #if defined(USING_CHROMIUM_INCLUDES)
41 // When building CEF include the Chromium header directly.
42 #include "base/callback_helpers.h"
43 #else  // !USING_CHROMIUM_INCLUDES
44 // The following is substantially similar to the Chromium implementation.
45 // If the Chromium implementation diverges the below implementation should be
46 // updated to match.
47 
48 #include <atomic>
49 #include <memory>
50 #include <type_traits>
51 #include <utility>
52 
53 #include "include/base/cef_bind.h"
54 #include "include/base/cef_callback.h"
55 #include "include/base/cef_compiler_specific.h"
56 #include "include/base/cef_logging.h"
57 
58 namespace base {
59 
60 namespace internal {
61 
62 template <typename T>
63 struct IsBaseCallbackImpl : std::false_type {};
64 
65 template <typename R, typename... Args>
66 struct IsBaseCallbackImpl<OnceCallback<R(Args...)>> : std::true_type {};
67 
68 template <typename R, typename... Args>
69 struct IsBaseCallbackImpl<RepeatingCallback<R(Args...)>> : std::true_type {};
70 
71 template <typename T>
72 struct IsOnceCallbackImpl : std::false_type {};
73 
74 template <typename R, typename... Args>
75 struct IsOnceCallbackImpl<OnceCallback<R(Args...)>> : std::true_type {};
76 
77 }  // namespace internal
78 
79 // IsBaseCallback<T>::value is true when T is any of the Closure or Callback
80 // family of types.
81 template <typename T>
82 using IsBaseCallback = internal::IsBaseCallbackImpl<std::decay_t<T>>;
83 
84 // IsOnceCallback<T>::value is true when T is a OnceClosure or OnceCallback
85 // type.
86 template <typename T>
87 using IsOnceCallback = internal::IsOnceCallbackImpl<std::decay_t<T>>;
88 
89 // SFINAE friendly enabler allowing to overload methods for both Repeating and
90 // OnceCallbacks.
91 //
92 // Usage:
93 // template <template <typename> class CallbackType,
94 //           ... other template args ...,
95 //           typename = EnableIfIsBaseCallback<CallbackType>>
96 // void DoStuff(CallbackType<...> cb, ...);
97 template <template <typename> class CallbackType>
98 using EnableIfIsBaseCallback =
99     std::enable_if_t<IsBaseCallback<CallbackType<void()>>::value>;
100 
101 namespace internal {
102 
103 template <typename... Args>
104 class OnceCallbackHolder final {
105  public:
106   OnceCallbackHolder(OnceCallback<void(Args...)> callback,
107                      bool ignore_extra_runs)
108       : callback_(std::move(callback)), ignore_extra_runs_(ignore_extra_runs) {
109     DCHECK(callback_);
110   }
111   OnceCallbackHolder(const OnceCallbackHolder&) = delete;
112   OnceCallbackHolder& operator=(const OnceCallbackHolder&) = delete;
113 
114   void Run(Args... args) {
115     if (has_run_.exchange(true)) {
116       CHECK(ignore_extra_runs_) << "Both OnceCallbacks returned by "
117                                    "base::SplitOnceCallback() were run. "
118                                    "At most one of the pair should be run.";
119       return;
120     }
121     DCHECK(callback_);
122     std::move(callback_).Run(std::forward<Args>(args)...);
123   }
124 
125  private:
126   volatile std::atomic_bool has_run_{false};
127   base::OnceCallback<void(Args...)> callback_;
128   const bool ignore_extra_runs_;
129 };
130 
131 }  // namespace internal
132 
133 // Wraps the given OnceCallback into a RepeatingCallback that relays its
134 // invocation to the original OnceCallback on the first invocation. The
135 // following invocations are just ignored.
136 //
137 // Note that this deliberately subverts the Once/Repeating paradigm of Callbacks
138 // but helps ease the migration from old-style Callbacks. Avoid if possible; use
139 // if necessary for migration. TODO(tzik): Remove it. https://crbug.com/730593
140 template <typename... Args>
141 RepeatingCallback<void(Args...)> AdaptCallbackForRepeating(
142     OnceCallback<void(Args...)> callback) {
143   using Helper = internal::OnceCallbackHolder<Args...>;
144   return base::BindRepeating(
145       &Helper::Run, std::make_unique<Helper>(std::move(callback),
146                                              /*ignore_extra_runs=*/true));
147 }
148 
149 // Wraps the given OnceCallback and returns two OnceCallbacks with an identical
150 // signature. On first invokation of either returned callbacks, the original
151 // callback is invoked. Invoking the remaining callback results in a crash.
152 template <typename... Args>
153 std::pair<OnceCallback<void(Args...)>, OnceCallback<void(Args...)>>
154 SplitOnceCallback(OnceCallback<void(Args...)> callback) {
155   using Helper = internal::OnceCallbackHolder<Args...>;
156   auto wrapped_once = base::BindRepeating(
157       &Helper::Run, std::make_unique<Helper>(std::move(callback),
158                                              /*ignore_extra_runs=*/false));
159   return std::make_pair(wrapped_once, wrapped_once);
160 }
161 
162 // ScopedClosureRunner is akin to std::unique_ptr<> for Closures. It ensures
163 // that the Closure is executed no matter how the current scope exits.
164 // If you are looking for "ScopedCallback", "CallbackRunner", or
165 // "CallbackScoper" this is the class you want.
166 class ScopedClosureRunner {
167  public:
168   ScopedClosureRunner();
169   explicit ScopedClosureRunner(OnceClosure closure);
170   ScopedClosureRunner(ScopedClosureRunner&& other);
171   // Runs the current closure if it's set, then replaces it with the closure
172   // from |other|. This is akin to how unique_ptr frees the contained pointer in
173   // its move assignment operator. If you need to explicitly avoid running any
174   // current closure, use ReplaceClosure().
175   ScopedClosureRunner& operator=(ScopedClosureRunner&& other);
176   ~ScopedClosureRunner();
177 
178   explicit operator bool() const { return !!closure_; }
179 
180   // Calls the current closure and resets it, so it wont be called again.
181   void RunAndReset();
182 
183   // Replaces closure with the new one releasing the old one without calling it.
184   void ReplaceClosure(OnceClosure closure);
185 
186   // Releases the Closure without calling.
187   OnceClosure Release() WARN_UNUSED_RESULT;
188 
189  private:
190   OnceClosure closure_;
191 };
192 
193 // Creates a null callback.
194 class NullCallback {
195  public:
196   template <typename R, typename... Args>
197   operator RepeatingCallback<R(Args...)>() const {
198     return RepeatingCallback<R(Args...)>();
199   }
200   template <typename R, typename... Args>
201   operator OnceCallback<R(Args...)>() const {
202     return OnceCallback<R(Args...)>();
203   }
204 };
205 
206 // Creates a callback that does nothing when called.
207 class DoNothing {
208  public:
209   template <typename... Args>
210   operator RepeatingCallback<void(Args...)>() const {
211     return Repeatedly<Args...>();
212   }
213   template <typename... Args>
214   operator OnceCallback<void(Args...)>() const {
215     return Once<Args...>();
216   }
217   // Explicit way of specifying a specific callback type when the compiler can't
218   // deduce it.
219   template <typename... Args>
220   static RepeatingCallback<void(Args...)> Repeatedly() {
221     return BindRepeating([](Args... args) {});
222   }
223   template <typename... Args>
224   static OnceCallback<void(Args...)> Once() {
225     return BindOnce([](Args... args) {});
226   }
227 };
228 
229 // Useful for creating a Closure that will delete a pointer when invoked. Only
230 // use this when necessary. In most cases MessageLoop::DeleteSoon() is a better
231 // fit.
232 template <typename T>
233 void DeletePointer(T* obj) {
234   delete obj;
235 }
236 
237 }  // namespace base
238 
239 #endif  // !USING_CHROMIUM_INCLUDES
240 
241 #endif  // CEF_INCLUDE_BASE_CEF_CALLBACK_HELPERS_H_
242