blob: 8d622f86552a5ec622b65a88d14ecf02316a2a99 [file] [log] [blame]
fischman@chromium.orgdc221a72012-03-25 05:37:27 +09001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// This defines helpful methods for dealing with Callbacks. Because Callbacks
6// are implemented using templates, with a class per callback signature, adding
7// methods to Callback<> itself is unattractive (lots of extra code gets
8// generated). Instead, consider adding methods here.
9//
10// ResetAndReturn(&cb) is like cb.Reset() but allows executing a callback (via a
michaelpgedf640b2017-03-18 11:49:09 +090011// move or copy) after the original callback is Reset(). This can be handy if
12// Run() reads/writes the variable holding the Callback.
fischman@chromium.orgdc221a72012-03-25 05:37:27 +090013
14#ifndef BASE_CALLBACK_HELPERS_H_
15#define BASE_CALLBACK_HELPERS_H_
16
tzik2c9ac662017-04-20 21:19:50 +090017#include <utility>
18
19#include "base/atomicops.h"
20#include "base/bind.h"
fischman@chromium.orgdc221a72012-03-25 05:37:27 +090021#include "base/callback.h"
avi@chromium.orgb74bab82013-08-30 11:04:04 +090022#include "base/compiler_specific.h"
avia6a6a682015-12-27 07:15:14 +090023#include "base/macros.h"
tzik2c9ac662017-04-20 21:19:50 +090024#include "base/memory/ptr_util.h"
fischman@chromium.orgdc221a72012-03-25 05:37:27 +090025
26namespace base {
27
tzik14e09b82017-01-28 06:20:14 +090028template <typename Signature,
29 internal::CopyMode copy_mode,
30 internal::RepeatMode repeat_mode>
tzik2c9ac662017-04-20 21:19:50 +090031Callback<Signature, copy_mode, repeat_mode> ResetAndReturn(
32 Callback<Signature, copy_mode, repeat_mode>* cb) {
33 Callback<Signature, copy_mode, repeat_mode> ret(std::move(*cb));
tzikcd0e2ce2017-02-22 18:13:19 +090034 DCHECK(!*cb);
fischman@chromium.orgdc221a72012-03-25 05:37:27 +090035 return ret;
36}
37
tzik2c9ac662017-04-20 21:19:50 +090038namespace internal {
39
40template <typename... Args>
41class AdaptCallbackForRepeatingHelper final {
42 public:
43 explicit AdaptCallbackForRepeatingHelper(OnceCallback<void(Args...)> callback)
44 : callback_(std::move(callback)) {
45 DCHECK(callback_);
46 }
47
48 void Run(Args... args) {
49 if (subtle::NoBarrier_AtomicExchange(&has_run_, 1))
50 return;
51 DCHECK(callback_);
52 std::move(callback_).Run(std::forward<Args>(args)...);
53 }
54
55 private:
56 volatile subtle::Atomic32 has_run_ = 0;
57 base::OnceCallback<void(Args...)> callback_;
58
59 DISALLOW_COPY_AND_ASSIGN(AdaptCallbackForRepeatingHelper);
60};
61
62} // namespace internal
63
64// Wraps the given OnceCallback into a RepeatingCallback that relays its
65// invocation to the original OnceCallback on the first invocation. The
66// following invocations are just ignored.
67template <typename... Args>
68RepeatingCallback<void(Args...)> AdaptCallbackForRepeating(
69 OnceCallback<void(Args...)> callback) {
70 using Helper = internal::AdaptCallbackForRepeatingHelper<Args...>;
71 return base::BindRepeating(&Helper::Run,
72 base::MakeUnique<Helper>(std::move(callback)));
73}
74
sergeyuf9cf2812016-06-25 09:51:09 +090075// ScopedClosureRunner is akin to std::unique_ptr<> for Closures. It ensures
76// that the Closure is executed no matter how the current scope exits.
avi@chromium.orgb74bab82013-08-30 11:04:04 +090077class BASE_EXPORT ScopedClosureRunner {
78 public:
79 ScopedClosureRunner();
80 explicit ScopedClosureRunner(const Closure& closure);
81 ~ScopedClosureRunner();
82
sergeyuf9cf2812016-06-25 09:51:09 +090083 ScopedClosureRunner(ScopedClosureRunner&& other);
84
sergeyu93396d12016-07-08 09:34:27 +090085 // Releases the current closure if it's set and replaces it with the closure
86 // from |other|.
sergeyuf9cf2812016-06-25 09:51:09 +090087 ScopedClosureRunner& operator=(ScopedClosureRunner&& other);
88
89 // Calls the current closure and resets it, so it wont be called again.
sergeyu93396d12016-07-08 09:34:27 +090090 void RunAndReset();
sergeyuf9cf2812016-06-25 09:51:09 +090091
sergeyu93396d12016-07-08 09:34:27 +090092 // Replaces closure with the new one releasing the old one without calling it.
93 void ReplaceClosure(const Closure& closure);
sergeyuf9cf2812016-06-25 09:51:09 +090094
95 // Releases the Closure without calling.
avi@chromium.orgb74bab82013-08-30 11:04:04 +090096 Closure Release() WARN_UNUSED_RESULT;
97
98 private:
99 Closure closure_;
100
101 DISALLOW_COPY_AND_ASSIGN(ScopedClosureRunner);
102};
103
fischman@chromium.orgdc221a72012-03-25 05:37:27 +0900104} // namespace base
105
106#endif // BASE_CALLBACK_HELPERS_H_